Internal Plugin
Ini adalah referensi arsitektur mendalam. Untuk panduan praktis, lihat:
- Instal dan gunakan plugin — panduan pengguna
- Memulai — tutorial plugin pertama
- Plugin Channel — bangun channel pesan
- Plugin Provider — bangun provider model
- Ikhtisar SDK — peta impor dan API pendaftaran
Model kapabilitas publik
Kapabilitas adalah model plugin native publik di dalam OpenClaw. Setiap plugin OpenClaw native mendaftar ke satu atau lebih tipe kapabilitas:| Kapabilitas | Metode pendaftaran | Contoh plugin |
|---|---|---|
| Inferensi teks | api.registerProvider(...) | openai, anthropic |
| Backend inferensi CLI | api.registerCliBackend(...) | openai, anthropic |
| Ucapan | api.registerSpeechProvider(...) | elevenlabs, microsoft |
| Transkripsi realtime | api.registerRealtimeTranscriptionProvider(...) | openai |
| Suara realtime | api.registerRealtimeVoiceProvider(...) | openai |
| Pemahaman media | api.registerMediaUnderstandingProvider(...) | openai, google |
| Pembuatan gambar | api.registerImageGenerationProvider(...) | openai, google, fal, minimax |
| Pembuatan musik | api.registerMusicGenerationProvider(...) | google, minimax |
| Pembuatan video | api.registerVideoGenerationProvider(...) | qwen |
| Pengambilan web | api.registerWebFetchProvider(...) | firecrawl |
| Pencarian web | api.registerWebSearchProvider(...) | google |
| Channel / pesan | api.registerChannel(...) | msteams, matrix |
Sikap kompatibilitas eksternal
Model kapabilitas sudah diterapkan di core dan digunakan oleh plugin bundled/native saat ini, tetapi kompatibilitas plugin eksternal masih memerlukan standar yang lebih ketat daripada “ini diekspor, jadi ini dibekukan.” Panduan saat ini:- plugin eksternal yang sudah ada: pertahankan integrasi berbasis hook tetap berfungsi; perlakukan ini sebagai baseline kompatibilitas
- plugin bundled/native baru: utamakan pendaftaran kapabilitas yang eksplisit daripada akses vendor-spesifik ke internal atau desain hook-only baru
- plugin eksternal yang mengadopsi pendaftaran kapabilitas: diperbolehkan, tetapi perlakukan surface helper khusus kapabilitas sebagai sesuatu yang berkembang kecuali dokumentasi secara eksplisit menandai kontrak sebagai stabil
- API pendaftaran kapabilitas adalah arah yang dituju
- hook legacy tetap menjadi jalur paling aman tanpa kerusakan untuk plugin eksternal selama masa transisi
- tidak semua subpath helper yang diekspor setara; pilih kontrak sempit yang didokumentasikan, bukan ekspor helper insidental
Bentuk plugin
OpenClaw mengklasifikasikan setiap plugin yang dimuat ke dalam suatu bentuk berdasarkan perilaku pendaftaran aktualnya (bukan hanya metadata statis):- plain-capability — mendaftarkan tepat satu tipe kapabilitas (misalnya
plugin provider-only seperti
mistral) - hybrid-capability — mendaftarkan beberapa tipe kapabilitas (misalnya
openaimemiliki inferensi teks, ucapan, pemahaman media, dan pembuatan gambar) - hook-only — hanya mendaftarkan hook (tertik atau kustom), tanpa kapabilitas, tool, perintah, atau layanan
- non-capability — mendaftarkan tool, perintah, layanan, atau rute tetapi tanpa kapabilitas
openclaw plugins inspect <id> untuk melihat bentuk plugin dan rincian
kapabilitasnya. Lihat referensi CLI untuk detail.
Hook legacy
Hookbefore_agent_start tetap didukung sebagai jalur kompatibilitas untuk
plugin hook-only. Plugin nyata legacy masih bergantung padanya.
Arah ke depan:
- pertahankan agar tetap berfungsi
- dokumentasikan sebagai legacy
- utamakan
before_model_resolveuntuk pekerjaan override model/provider - utamakan
before_prompt_builduntuk pekerjaan mutasi prompt - hapus hanya setelah penggunaan nyata menurun dan cakupan fixture membuktikan keamanan migrasi
Sinyal kompatibilitas
Saat Anda menjalankanopenclaw doctor atau openclaw plugins inspect <id>, Anda mungkin melihat
salah satu label berikut:
| Sinyal | Arti |
|---|---|
| config valid | Konfigurasi diparse dengan baik dan plugin berhasil di-resolve |
| compatibility advisory | Plugin menggunakan pola yang didukung tetapi lebih lama (mis. hook-only) |
| legacy warning | Plugin menggunakan before_agent_start, yang sudah deprecated |
| hard error | Konfigurasi tidak valid atau plugin gagal dimuat |
hook-only maupun before_agent_start tidak akan merusak plugin Anda saat ini —
hook-only bersifat advisory, dan before_agent_start hanya memicu peringatan. Sinyal-sinyal ini
juga muncul di openclaw status --all dan openclaw plugins doctor.
Ikhtisar arsitektur
Sistem plugin OpenClaw memiliki empat lapisan:- Manifest + discovery
OpenClaw menemukan kandidat plugin dari path yang dikonfigurasi, root workspace,
root extension global, dan extension bundled. Discovery membaca manifest native
openclaw.plugin.jsonserta manifest bundle yang didukung terlebih dahulu. - Enablement + validation Core memutuskan apakah plugin yang ditemukan diaktifkan, dinonaktifkan, diblokir, atau dipilih untuk slot eksklusif seperti memory.
- Runtime loading Plugin OpenClaw native dimuat in-process melalui jiti dan mendaftarkan kapabilitas ke registri pusat. Bundle yang kompatibel dinormalisasi menjadi catatan registri tanpa mengimpor kode runtime.
- Surface consumption Bagian lain dari OpenClaw membaca registri untuk mengekspos tool, channel, penyiapan provider, hook, rute HTTP, perintah CLI, dan layanan.
- metadata saat parse berasal dari
registerCli(..., { descriptors: [...] }) - modul CLI plugin yang sebenarnya dapat tetap lazy dan mendaftar pada pemanggilan pertama
- discovery + validasi konfigurasi harus bekerja dari metadata manifest/schema tanpa mengeksekusi kode plugin
- perilaku runtime native berasal dari jalur
register(api)modul plugin
Plugin channel dan tool pesan bersama
Plugin channel tidak perlu mendaftarkan tool kirim/edit/reaksi terpisah untuk aksi chat normal. OpenClaw mempertahankan satu toolmessage bersama di core, dan
plugin channel memiliki discovery dan eksekusi khusus channel di baliknya.
Batas saat ini adalah:
- core memiliki host tool
messagebersama, wiring prompt, pembukuan sesi/thread, dan dispatch eksekusi - plugin channel memiliki discovery aksi berscope, discovery kapabilitas, dan fragmen schema khusus channel
- plugin channel memiliki grammar percakapan sesi khusus provider, seperti bagaimana id percakapan mengodekan id thread atau mewarisi dari percakapan induk
- plugin channel mengeksekusi aksi akhir melalui adaptor aksi mereka
ChannelMessageActionAdapter.describeMessageTool(...). Panggilan discovery terpadu
itu memungkinkan plugin mengembalikan aksi yang terlihat, kapabilitas, dan kontribusi schema
secara bersama agar bagian-bagian itu tidak saling melenceng.
Ketika suatu param message-tool khusus channel membawa sumber media seperti
path lokal atau URL media jarak jauh, plugin juga harus mengembalikan
mediaSourceParams dari describeMessageTool(...). Core menggunakan daftar
eksplisit itu untuk menerapkan normalisasi path sandbox dan petunjuk akses media
keluar tanpa meng-hardcode nama param milik plugin.
Utamakan peta berscope aksi di sana, bukan satu daftar datar untuk seluruh channel, agar
param media khusus profil tidak dinormalisasi pada aksi yang tidak terkait seperti
send.
Core meneruskan scope runtime ke langkah discovery tersebut. Field penting meliputi:
accountIdcurrentChannelIdcurrentThreadTscurrentMessageIdsessionKeysessionIdagentIdrequesterSenderIdinbound tepercaya
message core.
Inilah sebabnya perubahan routing embedded-runner masih merupakan pekerjaan plugin: runner
bertanggung jawab untuk meneruskan identitas chat/sesi saat ini ke batas
discovery plugin agar tool message bersama mengekspos surface milik channel yang tepat
untuk giliran saat ini.
Untuk helper eksekusi milik channel, plugin bundled harus menjaga runtime eksekusi
tetap di dalam modul extension miliknya sendiri. Core tidak lagi memiliki runtime
aksi pesan Discord, Slack, Telegram, atau WhatsApp di bawah src/agents/tools.
Kami tidak memublikasikan subpath plugin-sdk/*-action-runtime terpisah, dan plugin bundled
harus mengimpor kode runtime lokalnya sendiri secara langsung dari
modul milik extension mereka.
Batas yang sama berlaku pada seam SDK bernama provider secara umum: core tidak boleh
mengimpor barrel kemudahan khusus channel untuk extension Slack, Discord, Signal,
WhatsApp, atau extension serupa. Jika core memerlukan suatu perilaku, maka
konsumsi barrel api.ts / runtime-api.ts milik plugin bundled itu sendiri atau promosikan kebutuhan tersebut
menjadi kapabilitas generik yang sempit di SDK bersama.
Khusus untuk poll, ada dua jalur eksekusi:
outbound.sendPolladalah baseline bersama untuk channel yang cocok dengan model poll umumactions.handleAction("poll")adalah jalur yang diutamakan untuk semantik poll khusus channel atau param poll tambahan
Model kepemilikan kapabilitas
OpenClaw memperlakukan plugin native sebagai batas kepemilikan untuk sebuah perusahaan atau sebuah fitur, bukan sebagai kumpulan acak integrasi yang tidak terkait. Artinya:- plugin perusahaan biasanya harus memiliki semua surface OpenClaw yang menghadap perusahaan tersebut
- plugin fitur biasanya harus memiliki seluruh surface fitur yang diperkenalkannya
- channel harus mengonsumsi kapabilitas core bersama alih-alih mengimplementasikan ulang perilaku provider secara ad hoc
- plugin
openaibundled memiliki perilaku model-provider OpenAI dan perilaku ucapan + suara realtime + pemahaman media + pembuatan gambar OpenAI - plugin
elevenlabsbundled memiliki perilaku ucapan ElevenLabs - plugin
microsoftbundled memiliki perilaku ucapan Microsoft - plugin
googlebundled memiliki perilaku model-provider Google ditambah perilaku pemahaman media + pembuatan gambar + pencarian web Google - plugin
firecrawlbundled memiliki perilaku pengambilan web Firecrawl - plugin
minimax,mistral,moonshot, danzaibundled memiliki backend pemahaman media mereka - plugin
qwenbundled memiliki perilaku text-provider Qwen ditambah perilaku pemahaman media dan pembuatan video - plugin
voice-calladalah plugin fitur: plugin ini memiliki transport panggilan, tool, CLI, rute, dan bridging media-stream Twilio, tetapi plugin ini mengonsumsi kapabilitas ucapan bersama ditambah transkripsi realtime dan suara realtime alih-alih mengimpor plugin vendor secara langsung
- OpenAI berada dalam satu plugin meskipun mencakup model teks, ucapan, gambar, dan video di masa depan
- vendor lain dapat melakukan hal yang sama untuk cakupan surface miliknya sendiri
- channel tidak peduli plugin vendor mana yang memiliki provider; mereka mengonsumsi kontrak kapabilitas bersama yang diekspos oleh core
- plugin = batas kepemilikan
- capability = kontrak core yang dapat diimplementasikan atau dikonsumsi oleh beberapa plugin
- definisikan kapabilitas yang belum ada di core
- ekspos kapabilitas itu melalui API/runtime plugin dengan cara yang tertik
- hubungkan channel/fitur ke kapabilitas itu
- biarkan plugin vendor mendaftarkan implementasi
Pelapisan kapabilitas
Gunakan model mental ini saat memutuskan di mana kode seharusnya berada:- lapisan kapabilitas core: orkestrasi bersama, kebijakan, fallback, konfigurasi aturan merge, semantik pengiriman, dan kontrak bertipe
- lapisan plugin vendor: API vendor-spesifik, autentikasi, katalog model, ucapan sintesis, pembuatan gambar, backend video masa depan, endpoint penggunaan
- lapisan plugin channel/fitur: integrasi Slack/Discord/voice-call/dll. yang mengonsumsi kapabilitas core dan menyajikannya pada suatu surface
- core memiliki kebijakan TTS saat balasan, urutan fallback, preferensi, dan pengiriman channel
openai,elevenlabs, danmicrosoftmemiliki implementasi sintesisvoice-callmengonsumsi helper runtime TTS teleponi
Contoh plugin perusahaan multi-kapabilitas
Plugin perusahaan harus terasa kohesif dari luar. Jika OpenClaw memiliki kontrak bersama untuk model, ucapan, transkripsi realtime, suara realtime, pemahaman media, pembuatan gambar, pembuatan video, pengambilan web, dan pencarian web, sebuah vendor dapat memiliki semua surface-nya di satu tempat:- satu plugin memiliki surface vendor
- core tetap memiliki kontrak kapabilitas
- channel dan plugin fitur mengonsumsi helper
api.runtime.*, bukan kode vendor - pengujian kontrak dapat menegaskan bahwa plugin telah mendaftarkan kapabilitas yang diklaimnya sebagai miliknya
Contoh kapabilitas: pemahaman video
OpenClaw sudah memperlakukan pemahaman gambar/audio/video sebagai satu kapabilitas bersama. Model kepemilikan yang sama juga berlaku di sana:- core mendefinisikan kontrak pemahaman media
- plugin vendor mendaftarkan
describeImage,transcribeAudio, dandescribeVideosesuai kebutuhan - channel dan plugin fitur mengonsumsi perilaku core bersama alih-alih menghubungkan langsung ke kode vendor
api.registerVideoGenerationProvider(...) terhadapnya.
Butuh checklist rollout yang konkret? Lihat
Capability Cookbook.
Kontrak dan enforcement
Surface API plugin sengaja dibuat bertipe dan terpusat diOpenClawPluginApi. Kontrak itu mendefinisikan titik pendaftaran yang didukung dan
helper runtime yang dapat diandalkan oleh plugin.
Mengapa ini penting:
- penulis plugin mendapatkan satu standar internal yang stabil
- core dapat menolak kepemilikan ganda seperti dua plugin yang mendaftarkan id provider yang sama
- startup dapat menampilkan diagnostik yang dapat ditindaklanjuti untuk pendaftaran yang malformed
- pengujian kontrak dapat menegakkan kepemilikan plugin bundled dan mencegah drift diam-diam
- enforcement pendaftaran runtime Registri plugin memvalidasi pendaftaran saat plugin dimuat. Contoh: id provider ganda, id speech provider ganda, dan pendaftaran yang malformed menghasilkan diagnostik plugin alih-alih perilaku yang tidak terdefinisi.
- pengujian kontrak Plugin bundled ditangkap dalam registri kontrak selama pengujian berjalan sehingga OpenClaw dapat menegaskan kepemilikan secara eksplisit. Saat ini ini digunakan untuk model provider, speech provider, web search provider, dan kepemilikan pendaftaran bundled.
Apa yang termasuk dalam sebuah kontrak
Kontrak plugin yang baik adalah:- bertipe
- kecil
- spesifik terhadap kapabilitas
- dimiliki oleh core
- dapat digunakan ulang oleh beberapa plugin
- dapat dikonsumsi oleh channel/fitur tanpa pengetahuan vendor
- kebijakan vendor-spesifik yang tersembunyi di core
- jalur lolos plugin sekali pakai yang melewati registri
- kode channel yang langsung masuk ke implementasi vendor
- objek runtime ad hoc yang bukan bagian dari
OpenClawPluginApiatauapi.runtime
Model eksekusi
Plugin OpenClaw native berjalan in-process dengan Gateway. Plugin ini tidak disandbox. Plugin native yang dimuat memiliki batas kepercayaan tingkat proses yang sama dengan kode core. Implikasinya:- plugin native dapat mendaftarkan tool, network handler, hook, dan layanan
- bug pada plugin native dapat membuat gateway crash atau tidak stabil
- plugin native yang berbahaya setara dengan eksekusi kode arbitrer di dalam proses OpenClaw
@openclaw/<id> secara default, atau sufiks bertipe yang disetujui seperti
-provider, -plugin, -speech, -sandbox, atau -media-understanding ketika
paket tersebut dengan sengaja mengekspos peran plugin yang lebih sempit.
Catatan kepercayaan penting:
plugins.allowmempercayai id plugin, bukan asal sumbernya.- Plugin workspace dengan id yang sama seperti plugin bundled dengan sengaja membayangi salinan bundled ketika plugin workspace itu diaktifkan/masuk allowlist.
- Ini normal dan berguna untuk pengembangan lokal, pengujian patch, dan hotfix.
Batas ekspor
OpenClaw mengekspor kapabilitas, bukan kemudahan implementasi. Pertahankan pendaftaran kapabilitas sebagai publik. Pangkas ekspor helper non-kontrak:- subpath helper khusus plugin bundled
- subpath plumbing runtime yang tidak dimaksudkan sebagai API publik
- helper kemudahan vendor-spesifik
- helper penyiapan/onboarding yang merupakan detail implementasi
plugin-sdk/feishu, plugin-sdk/feishu-setup, plugin-sdk/zalo,
plugin-sdk/zalo-setup, dan beberapa seam plugin-sdk/matrix*. Perlakukan itu sebagai
ekspor detail implementasi yang dicadangkan, bukan sebagai pola SDK yang direkomendasikan untuk
plugin pihak ketiga baru.
Pipeline pemuatan
Saat startup, OpenClaw secara garis besar melakukan ini:- menemukan root plugin kandidat
- membaca manifest native atau bundle yang kompatibel dan metadata paket
- menolak kandidat yang tidak aman
- menormalisasi konfigurasi plugin (
plugins.enabled,allow,deny,entries,slots,load.paths) - memutuskan enablement untuk setiap kandidat
- memuat modul native yang diaktifkan melalui jiti
- memanggil hook native
register(api)(atauactivate(api)— alias legacy) dan mengumpulkan pendaftaran ke dalam registri plugin - mengekspos registri ke surface perintah/runtime
activate adalah alias legacy untuk register — loader me-resolve mana pun yang ada (def.register ?? def.activate) dan memanggilnya pada titik yang sama. Semua plugin bundled menggunakan register; utamakan register untuk plugin baru.Perilaku manifest-first
Manifest adalah source of truth control-plane. OpenClaw menggunakannya untuk:- mengidentifikasi plugin
- menemukan channel/Skills/schema konfigurasi yang dideklarasikan atau kapabilitas bundle
- memvalidasi
plugins.entries.<id>.config - menambah label/placeholder Control UI
- menampilkan metadata instalasi/katalog
- mempertahankan descriptor aktivasi dan penyiapan yang ringan tanpa memuat runtime plugin
activation dan setup manifest opsional tetap berada di control plane.
Blok ini adalah descriptor metadata saja untuk perencanaan aktivasi dan discovery penyiapan;
blok ini tidak menggantikan pendaftaran runtime, register(...), atau setupEntry.
Konsumen aktivasi live pertama sekarang menggunakan petunjuk perintah, channel, dan provider
pada manifest untuk mempersempit pemuatan plugin sebelum materialisasi registri yang lebih luas:
- pemuatan CLI dipersempit ke plugin yang memiliki perintah utama yang diminta
- resolusi setup/plugin channel dipersempit ke plugin yang memiliki id channel yang diminta
- resolusi setup/runtime provider eksplisit dipersempit ke plugin yang memiliki id provider yang diminta
setup.providers dan
setup.cliBackends untuk mempersempit plugin kandidat sebelum kembali ke
setup-api untuk plugin yang masih memerlukan hook runtime saat setup. Jika lebih dari
satu plugin yang ditemukan mengklaim id provider setup atau backend CLI yang sama setelah dinormalisasi,
lookup setup menolak pemilik yang ambigu tersebut alih-alih bergantung pada urutan
discovery.
Apa yang di-cache oleh loader
OpenClaw menyimpan cache in-process jangka pendek untuk:- hasil discovery
- data registri manifest
- registri 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 registri
Plugin yang dimuat tidak langsung memutasi global core acak. Plugin mendaftar ke dalam registri plugin pusat. Registri melacak:- catatan plugin (identitas, sumber, asal, status, diagnostik)
- tool
- hook legacy dan hook bertipe
- channel
- provider
- handler RPC Gateway
- rute HTTP
- registrar CLI
- layanan latar belakang
- perintah milik plugin
- modul plugin -> pendaftaran registri
- runtime core -> konsumsi registri
Callback pengikatan percakapan
Plugin yang mengikat percakapan dapat bereaksi ketika persetujuan diselesaikan. Gunakanapi.onConversationBindingResolved(...) untuk menerima callback setelah sebuah permintaan bind
disetujui atau ditolak:
status:"approved"atau"denied"decision:"allow-once","allow-always", atau"deny"binding: binding yang telah diselesaikan untuk permintaan yang disetujuirequest: ringkasan permintaan asli, petunjuk detach, id pengirim, dan metadata percakapan
Hook runtime provider
Plugin provider sekarang memiliki dua lapisan:- metadata manifest:
providerAuthEnvVarsuntuk lookup auth env provider yang ringan sebelum runtime dimuat,providerAuthAliasesuntuk varian provider yang berbagi auth,channelEnvVarsuntuk lookup env/setup channel yang ringan sebelum runtime dimuat, ditambahproviderAuthChoicesuntuk label onboarding/pilihan auth yang ringan dan metadata flag CLI sebelum runtime dimuat - hook saat konfigurasi:
catalog/discoverylegacy ditambahapplyConfigDefaults - hook runtime:
normalizeModelId,normalizeTransport,normalizeConfig,applyNativeStreamingUsageCompat,resolveConfigApiKey,resolveSyntheticAuth,resolveExternalAuthProfiles,shouldDeferSyntheticProfileAuth,resolveDynamicModel,prepareDynamicModel,normalizeResolvedModel,contributeResolvedModelCompat,capabilities,normalizeToolSchemas,inspectToolSchemas,resolveReasoningOutputMode,prepareExtraParams,createStreamFn,wrapStreamFn,resolveTransportTurnState,resolveWebSocketSessionPolicy,formatApiKey,refreshOAuth,buildAuthDoctorHint,matchesContextOverflowError,classifyFailoverReason,isCacheTtlEligible,buildMissingAuthMessage,suppressBuiltInModel,augmentModelCatalog,isBinaryThinking,supportsXHighThinking,resolveDefaultThinkingLevel,isModernModelRef,prepareRuntimeAuth,resolveUsageAuth,fetchUsageSnapshot,createEmbeddingProvider,buildReplayPolicy,sanitizeReplayHistory,validateReplayTurns,onModelSelected
providerAuthEnvVars ketika provider memiliki kredensial berbasis env
yang harus dapat dilihat oleh jalur auth/status/model-picker generik tanpa memuat runtime plugin.
Gunakan manifest providerAuthAliases ketika satu id provider harus menggunakan ulang
env var, profil auth, auth berbasis konfigurasi, dan pilihan onboarding API-key dari id provider lain.
Gunakan manifest providerAuthChoices ketika surface CLI onboarding/pilihan-auth
harus 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 variabel setup OAuth client-id/client-secret.
Gunakan manifest channelEnvVars ketika sebuah channel memiliki auth atau setup berbasis env yang
harus dapat dilihat oleh fallback shell-env generik, pemeriksaan config/status, atau prompt setup
tanpa memuat runtime channel.
Urutan hook dan penggunaannya
Untuk plugin model/provider, OpenClaw memanggil hook dalam urutan kasar ini. Kolom “When to use” adalah panduan keputusan cepat.| # | Hook | Apa fungsinya | Kapan digunakan |
|---|---|---|---|
| 1 | catalog | Mempublikasikan konfigurasi provider ke models.providers selama pembuatan models.json | Provider memiliki katalog atau default base URL |
| 2 | applyConfigDefaults | Menerapkan default konfigurasi global milik provider selama materialisasi konfigurasi | Default bergantung pada mode auth, env, atau semantik keluarga model provider |
| — | (lookup model bawaan) | OpenClaw mencoba jalur registri/katalog normal terlebih dahulu | (bukan hook plugin) |
| 3 | normalizeModelId | Menormalkan alias model-id legacy atau pratinjau sebelum lookup | Provider memiliki pembersihan alias sebelum resolusi model kanonis |
| 4 | normalizeTransport | Menormalkan api / baseUrl keluarga provider 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 memerlukan pembersihan konfigurasi yang seharusnya berada bersama plugin; helper keluarga Google bundled juga menopang entri konfigurasi Google yang didukung |
| 6 | applyNativeStreamingUsageCompat | Menerapkan penulisan ulang kompatibilitas native streaming-usage ke provider konfigurasi | Provider memerlukan perbaikan metadata native streaming usage yang digerakkan oleh endpoint |
| 7 | resolveConfigApiKey | Me-resolve auth penanda env untuk provider konfigurasi 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 auth berbasis konfigurasi tanpa menyimpan plaintext | Provider dapat beroperasi dengan penanda kredensial synthetic/lokal |
| 9 | resolveExternalAuthProfiles | Melapisi profil auth eksternal milik provider; default persistence adalah runtime-only untuk kredensial milik CLI/app | Provider menggunakan ulang kredensial auth eksternal tanpa menyimpan refresh token hasil salin |
| 10 | shouldDeferSyntheticProfileAuth | Menurunkan prioritas placeholder profil synthetic yang tersimpan di bawah auth berbasis env/konfigurasi | Provider menyimpan profil placeholder synthetic yang seharusnya tidak menang prioritas |
| 11 | resolveDynamicModel | Fallback sinkron untuk id model milik provider yang belum ada di registri lokal | Provider menerima id model upstream arbitrer |
| 12 | prepareDynamicModel | Warm-up asinkron, lalu resolveDynamicModel dijalankan lagi | Provider memerlukan metadata jaringan sebelum me-resolve id yang tidak dikenal |
| 13 | normalizeResolvedModel | Penulisan ulang final sebelum embedded runner menggunakan model yang telah di-resolve | Provider memerlukan penulisan ulang transport tetapi tetap menggunakan transport core |
| 14 | contributeResolvedModelCompat | Menyumbangkan flag kompatibilitas untuk model vendor di balik transport kompatibel lain | Provider mengenali modelnya sendiri pada transport proksi tanpa mengambil alih provider |
| 15 | capabilities | Metadata transkrip/tooling milik provider yang digunakan oleh logika core bersama | Provider memerlukan keunikan transkrip/keluarga provider |
| 16 | normalizeToolSchemas | Menormalkan schema tool sebelum embedded runner melihatnya | Provider memerlukan pembersihan schema keluarga transport |
| 17 | inspectToolSchemas | Menampilkan diagnostik schema milik provider setelah normalisasi | Provider ingin peringatan keyword tanpa mengajarkan aturan provider-spesifik ke core |
| 18 | resolveReasoningOutputMode | Memilih kontrak output reasoning native vs bertag | Provider memerlukan output reasoning/final bertag alih-alih field native |
| 19 | prepareExtraParams | Normalisasi param permintaan sebelum wrapper opsi stream generik | Provider memerlukan param permintaan default atau pembersihan param per-provider |
| 20 | createStreamFn | Sepenuhnya mengganti jalur stream normal dengan transport kustom | Provider memerlukan wire protocol kustom, bukan sekadar wrapper |
| 21 | wrapStreamFn | Wrapper stream setelah wrapper generik diterapkan | Provider memerlukan wrapper kompatibilitas header/body/model permintaan tanpa transport kustom |
| 22 | resolveTransportTurnState | Melampirkan header atau metadata transport per-turn native | Provider ingin transport generik mengirim identitas turn 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 profil auth: profil yang tersimpan menjadi string apiKey runtime | Provider menyimpan metadata auth tambahan dan memerlukan bentuk token runtime kustom |
| 25 | refreshOAuth | Override refresh OAuth untuk endpoint refresh kustom atau kebijakan kegagalan refresh | Provider tidak cocok dengan refresher pi-ai bersama |
| 26 | buildAuthDoctorHint | Petunjuk perbaikan yang ditambahkan saat refresh OAuth gagal | Provider memerlukan panduan perbaikan auth milik provider setelah refresh gagal |
| 27 | matchesContextOverflowError | Matcher overflow context-window milik provider | Provider memiliki error overflow mentah yang akan terlewat oleh heuristik generik |
| 28 | classifyFailoverReason | Klasifikasi alasan failover milik provider | Provider dapat memetakan error API/transport mentah ke rate-limit/overload/dll. |
| 29 | isCacheTtlEligible | Kebijakan prompt-cache untuk provider proksi/backhaul | Provider memerlukan pengaturan cache TTL khusus proksi |
| 30 | buildMissingAuthMessage | Pengganti pesan pemulihan missing-auth generik | Provider memerlukan petunjuk pemulihan missing-auth yang spesifik untuk provider |
| 31 | suppressBuiltInModel | Penekanan model upstream usang ditambah petunjuk error opsional yang menghadap pengguna | Provider perlu menyembunyikan baris upstream yang usang atau menggantinya dengan petunjuk vendor |
| 32 | augmentModelCatalog | Baris katalog synthetic/final yang ditambahkan setelah discovery | Provider memerlukan baris forward-compat synthetic di models list dan picker |
| 33 | isBinaryThinking | Toggle reasoning hidup/mati untuk provider binary-thinking | Provider hanya mengekspos binary thinking hidup/mati |
| 34 | supportsXHighThinking | Dukungan reasoning xhigh untuk model tertentu | Provider ingin xhigh hanya pada subset model tertentu |
| 35 | resolveDefaultThinkingLevel | Level /think default untuk keluarga model tertentu | Provider memiliki kebijakan /think default untuk suatu keluarga model |
| 36 | isModernModelRef | Matcher model modern untuk filter profil live dan pemilihan smoke | Provider memiliki pencocokan preferred-model live/smoke |
| 37 | prepareRuntimeAuth | Menukar kredensial yang dikonfigurasi menjadi token/key runtime aktual tepat sebelum inferensi | Provider memerlukan pertukaran token atau kredensial permintaan berumur pendek |
| 38 | resolveUsageAuth | Me-resolve kredensial penggunaan/penagihan untuk /usage dan surface status terkait | Provider memerlukan parsing token penggunaan/kuota kustom atau kredensial penggunaan yang berbeda |
| 39 | fetchUsageSnapshot | Mengambil dan menormalkan snapshot penggunaan/kuota provider-spesifik setelah auth di-resolve | Provider memerlukan endpoint penggunaan atau parser payload yang spesifik untuk provider |
| 40 | createEmbeddingProvider | Membangun adaptor embedding milik provider untuk memory/search | Perilaku embedding memory harus berada bersama plugin provider |
| 41 | buildReplayPolicy | Mengembalikan kebijakan replay yang mengontrol penanganan transkrip untuk provider | Provider memerlukan kebijakan transkrip kustom (misalnya, menghapus blok thinking) |
| 42 | sanitizeReplayHistory | Menulis ulang riwayat replay setelah pembersihan transkrip generik | Provider memerlukan penulisan ulang replay yang spesifik untuk provider di luar helper Compaction bersama |
| 43 | validateReplayTurns | Validasi atau pembentukan ulang replay-turn final sebelum embedded runner | Transport provider memerlukan validasi turn yang lebih ketat setelah sanitasi generik |
| 44 | onModelSelected | Menjalankan efek samping pasca-pemilihan milik provider | Provider memerlukan telemetri 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 menggunakan hook
sampai salah satunya benar-benar mengubah model id atau transport/config. Ini menjaga
shim provider alias/kompatibilitas tetap berfungsi tanpa mengharuskan pemanggil mengetahui plugin
bundled mana yang memiliki penulisan ulang tersebut. Jika tidak ada hook provider yang menulis ulang
entri konfigurasi keluarga Google yang didukung, normalizer konfigurasi Google bundled tetap menerapkan
pembersihan kompatibilitas tersebut.
Jika provider memerlukan wire protocol yang sepenuhnya kustom atau eksekutor permintaan kustom,
itu adalah kelas extension yang berbeda. Hook ini ditujukan untuk perilaku provider
yang tetap berjalan pada loop inferensi normal OpenClaw.
Contoh provider
Contoh bawaan
- Anthropic menggunakan
resolveDynamicModel,capabilities,buildAuthDoctorHint,resolveUsageAuth,fetchUsageSnapshot,isCacheTtlEligible,resolveDefaultThinkingLevel,applyConfigDefaults,isModernModelRef, danwrapStreamFnkarena plugin ini memiliki forward-compat Claude 4.6, petunjuk keluarga provider, panduan perbaikan auth, integrasi endpoint penggunaan, kelayakan prompt-cache, default konfigurasi yang sadar auth, kebijakan thinking default/adaptif Claude, dan pembentukan stream khusus Anthropic untuk beta header,/fast/serviceTier, dancontext1m. - Helper stream khusus Claude milik Anthropic untuk saat ini tetap berada di
seam
api.ts/contract-api.tspublik milik plugin bundled itu sendiri. Surface paket tersebut mengeksporwrapAnthropicProviderStream,resolveAnthropicBetas,resolveAnthropicFastMode,resolveAnthropicServiceTier, dan builder wrapper Anthropic tingkat lebih rendah alih-alih memperluas SDK generik di sekitar aturan beta-header satu provider. - OpenAI menggunakan
resolveDynamicModel,normalizeResolvedModel, dancapabilitiesditambahbuildMissingAuthMessage,suppressBuiltInModel,augmentModelCatalog,supportsXHighThinking, danisModernModelRefkarena plugin ini memiliki forward-compat GPT-5.4, normalisasi langsung OpenAIopenai-completions->openai-responses, petunjuk auth yang sadar Codex, suppressi Spark, baris daftar OpenAI synthetic, dan kebijakan thinking / live-model GPT-5; keluarga streamopenai-responses-defaultsmemiliki wrapper OpenAI Responses native bersama untuk attribution header,/fast/serviceTier, text verbosity, pencarian web native Codex, pembentukan payload reasoning-compat, dan manajemen konteks Responses. - OpenRouter menggunakan
catalogditambahresolveDynamicModeldanprepareDynamicModelkarena provider ini bersifat pass-through dan dapat mengekspos model id baru sebelum katalog statis OpenClaw diperbarui; plugin ini juga menggunakancapabilities,wrapStreamFn, danisCacheTtlEligibleuntuk menjaga header permintaan spesifik provider, metadata routing, patch reasoning, dan kebijakan prompt-cache tetap berada di luar core. Kebijakan replay-nya berasal dari keluargapassthrough-gemini, sedangkan keluarga streamopenrouter-thinkingmemiliki injeksi reasoning proksi dan skip model yang tidak didukung /auto. - GitHub Copilot menggunakan
catalog,auth,resolveDynamicModel, dancapabilitiesditambahprepareRuntimeAuthdanfetchUsageSnapshotkarena plugin ini memerlukan device login milik provider, perilaku fallback model, keunikan transkrip Claude, pertukaran token GitHub -> token Copilot, dan endpoint penggunaan milik provider. - OpenAI Codex menggunakan
catalog,resolveDynamicModel,normalizeResolvedModel,refreshOAuth, danaugmentModelCatalogditambahprepareExtraParams,resolveUsageAuth, danfetchUsageSnapshotkarena plugin ini masih berjalan di atas transport OpenAI core tetapi memiliki normalisasi transport/base URL, kebijakan fallback refresh OAuth, pilihan transport default, baris katalog Codex synthetic, dan integrasi endpoint penggunaan ChatGPT; plugin ini berbagi keluarga streamopenai-responses-defaultsyang sama dengan OpenAI langsung. - Google AI Studio dan Gemini CLI OAuth menggunakan
resolveDynamicModel,buildReplayPolicy,sanitizeReplayHistory,resolveReasoningOutputMode,wrapStreamFn, danisModernModelRefkarena keluarga replaygoogle-geminimemiliki fallback forward-compat Gemini 3.1, validasi replay Gemini native, sanitasi replay bootstrap, mode output reasoning bertag, dan pencocokan model modern, sedangkan keluarga streamgoogle-thinkingmemiliki normalisasi payload thinking Gemini; Gemini CLI OAuth juga menggunakanformatApiKey,resolveUsageAuth, danfetchUsageSnapshotuntuk formatting token, parsing token, dan wiring endpoint kuota. - Anthropic Vertex menggunakan
buildReplayPolicymelalui keluarga replayanthropic-by-modelsehingga pembersihan replay khusus Claude tetap dibatasi pada id Claude alih-alih setiap transportanthropic-messages. - Amazon Bedrock menggunakan
buildReplayPolicy,matchesContextOverflowError,classifyFailoverReason, danresolveDefaultThinkingLevelkarena plugin ini memiliki klasifikasi error throttle/not-ready/context-overflow khusus Bedrock untuk lalu lintas Anthropic-on-Bedrock; kebijakan replay-nya tetap berbagi guardanthropic-by-modelkhusus Claude yang sama. - OpenRouter, Kilocode, Opencode, dan Opencode Go menggunakan
buildReplayPolicymelalui keluarga replaypassthrough-geminikarena mereka memproksikan model Gemini melalui transport yang kompatibel dengan OpenAI dan memerlukan sanitasi thought-signature Gemini tanpa validasi replay Gemini native atau penulisan ulang bootstrap. - MiniMax menggunakan
buildReplayPolicymelalui keluarga replayhybrid-anthropic-openaikarena satu provider memiliki semantik pesan Anthropic dan OpenAI-compatible; plugin ini mempertahankan penghapusan blok thinking khusus Claude di sisi Anthropic sambil meng-override mode output reasoning kembali ke native, dan keluarga streamminimax-fast-modememiliki penulisan ulang model fast-mode pada jalur stream bersama. - Moonshot menggunakan
catalogditambahwrapStreamFnkarena plugin ini masih menggunakan transport OpenAI bersama tetapi memerlukan normalisasi payload thinking milik provider; keluarga streammoonshot-thinkingmemetakan konfigurasi ditambah state/thinkke payload binary thinking native-nya. - Kilocode menggunakan
catalog,capabilities,wrapStreamFn, danisCacheTtlEligiblekarena plugin ini memerlukan header permintaan milik provider, normalisasi payload reasoning, petunjuk transkrip Gemini, dan pengaturan cache-TTL Anthropic; keluarga streamkilocode-thinkingmenjaga injeksi thinking Kilo tetap berada pada jalur stream proksi bersama sambil melewatikilo/autodan model id proksi lain yang tidak mendukung payload reasoning eksplisit. - Z.AI menggunakan
resolveDynamicModel,prepareExtraParams,wrapStreamFn,isCacheTtlEligible,isBinaryThinking,isModernModelRef,resolveUsageAuth, danfetchUsageSnapshotkarena plugin ini memiliki fallback GLM-5, defaulttool_stream, UX binary thinking, pencocokan model modern, dan pengambilan auth penggunaan + kuota; keluarga streamtool-stream-default-onmenjaga wrappertool_streamdefault-on tetap berada di luar glue tulisan tangan per-provider. - xAI menggunakan
normalizeResolvedModel,normalizeTransport,contributeResolvedModelCompat,prepareExtraParams,wrapStreamFn,resolveSyntheticAuth,resolveDynamicModel, danisModernModelRefkarena plugin ini memiliki normalisasi transport xAI Responses native, penulisan ulang alias fast-mode Grok, defaulttool_stream, pembersihan strict-tool / payload reasoning, penggunaan ulang auth fallback untuk tool milik plugin, resolusi model Grok forward-compat, dan patch kompatibilitas milik provider seperti profil tool-schema xAI, keyword schema yang tidak didukung,web_searchnative, dan decoding argumen tool-call entitas HTML. - Mistral, OpenCode Zen, dan OpenCode Go hanya menggunakan
capabilitiesuntuk menjaga keunikan transkrip/tooling tetap berada di luar core. - Provider bundled yang hanya katalog seperti
byteplus,cloudflare-ai-gateway,huggingface,kimi-coding,nvidia,qianfan,synthetic,together,venice,vercel-ai-gateway, danvolcenginemenggunakancatalogsaja. - Qwen menggunakan
cataloguntuk text provider-nya ditambah pendaftaran shared media-understanding dan video-generation untuk surface multimodal-nya. - MiniMax dan Xiaomi menggunakan
catalogditambah hook penggunaan karena perilaku/usagemereka dimiliki plugin meskipun inferensi tetap berjalan melalui transport bersama.
Helper runtime
Plugin dapat mengakses helper core tertentu melaluiapi.runtime. Untuk TTS:
textToSpeechmengembalikan payload keluaran TTS core normal untuk surface file/catatan suara.- Menggunakan konfigurasi core
messages.ttsdan pemilihan provider. - Mengembalikan buffer audio PCM + sample rate. Plugin harus melakukan resample/encode untuk provider.
listVoicesbersifat opsional per provider. Gunakan ini untuk voice picker milik vendor atau alur setup.- Daftar suara dapat mencakup metadata yang lebih kaya seperti locale, gender, dan tag personality untuk picker yang sadar provider.
- OpenAI dan ElevenLabs saat ini mendukung teleponi. Microsoft tidak.
api.registerSpeechProvider(...).
- Pertahankan kebijakan TTS, fallback, dan pengiriman balasan di core.
- Gunakan speech provider untuk perilaku sintesis milik vendor.
- Input
edgeMicrosoft legacy dinormalisasi ke id providermicrosoft. - Model kepemilikan yang diutamakan berorientasi perusahaan: satu plugin vendor dapat memiliki provider teks, ucapan, gambar, dan media di masa depan saat OpenClaw menambahkan kontrak kapabilitas tersebut.
- Pertahankan orkestrasi, fallback, konfigurasi, dan wiring channel di core.
- Pertahankan perilaku vendor di plugin provider.
- Ekspansi aditif harus tetap bertipe: metode opsional baru, field hasil opsional baru, kapabilitas opsional baru.
- Pembuatan video sudah mengikuti pola yang sama:
- core memiliki kontrak kapabilitas dan helper runtime
- plugin vendor mendaftarkan
api.registerVideoGenerationProvider(...) - plugin fitur/channel mengonsumsi
api.runtime.videoGeneration.*
api.runtime.mediaUnderstanding.*adalah surface bersama yang diutamakan untuk pemahaman gambar/audio/video.- Menggunakan konfigurasi audio media-understanding core (
tools.media.audio) dan urutan fallback provider. - Mengembalikan
{ text: undefined }ketika tidak ada keluaran transkripsi yang dihasilkan (misalnya input dilewati/tidak didukung). api.runtime.stt.transcribeAudioFile(...)tetap ada sebagai alias kompatibilitas.
api.runtime.subagent:
providerdanmodeladalah override per eksekusi yang opsional, bukan perubahan sesi yang persisten.- OpenClaw hanya menghormati field override tersebut untuk pemanggil tepercaya.
- Untuk eksekusi fallback milik plugin, operator harus melakukan opt-in dengan
plugins.entries.<id>.subagent.allowModelOverride: true. - Gunakan
plugins.entries.<id>.subagent.allowedModelsuntuk membatasi plugin tepercaya ke target kanonisprovider/modeltertentu, atau"*"untuk secara eksplisit mengizinkan target apa pun. - Eksekusi 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 core.
- Gunakan web-search provider untuk transport pencarian vendor-spesifik.
api.runtime.webSearch.*adalah surface bersama yang diutamakan untuk plugin fitur/channel yang memerlukan perilaku pencarian tanpa bergantung pada wrapper tool agen.
api.runtime.imageGeneration
generate(...): hasilkan gambar menggunakan rantai provider pembuatan gambar yang dikonfigurasi.listProviders(...): daftar provider pembuatan gambar yang tersedia dan kapabilitasnya.
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 yang sudah ada miliknya sendiri.handler: kembalikantruesaat rute menangani permintaan.
api.registerHttpHandler(...)telah dihapus dan akan menyebabkan error saat pemuatan plugin. Gunakanapi.registerHttpRoute(...)sebagai gantinya.- Rute plugin harus mendeklarasikan
authsecara eksplisit. - Konflik
path + matchyang persis sama ditolak kecualireplaceExisting: true, dan satu plugin tidak dapat mengganti rute 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 panggilan helper Gateway berprivileg. - Rute
auth: "gateway"berjalan di dalam scope runtime permintaan Gateway, tetapi scope itu sengaja konservatif:- auth bearer shared-secret (
gateway.auth.mode = "token"/"password") menjaga scope runtime rute plugin tetap terkunci padaoperator.write, bahkan jika pemanggil mengirimx-openclaw-scopes - mode HTTP tepercaya yang membawa identitas (misalnya
trusted-proxyataugateway.auth.mode = "none"pada ingress privat) menghormatix-openclaw-scopeshanya ketika header tersebut memang ada - jika
x-openclaw-scopestidak ada pada permintaan rute plugin yang membawa identitas tersebut, scope runtime fallback keoperator.write
- auth bearer shared-secret (
- Aturan praktis: jangan menganggap rute plugin dengan auth gateway sebagai surface admin implisit. Jika rute Anda memerlukan perilaku khusus admin, wajibkan mode auth yang membawa identitas dan dokumentasikan kontrak header
x-openclaw-scopesyang eksplisit.
Path impor Plugin SDK
Gunakan subpath SDK alih-alih impor monolitikopenclaw/plugin-sdk saat
menulis plugin:
openclaw/plugin-sdk/plugin-entryuntuk primitif pendaftaran plugin.openclaw/plugin-sdk/coreuntuk kontrak umum bersama yang menghadap plugin.openclaw/plugin-sdk/config-schemauntuk ekspor skema Zod rootopenclaw.json(OpenClawSchema).- Primitif channel stabil seperti
openclaw/plugin-sdk/channel-setup,openclaw/plugin-sdk/setup-runtime,openclaw/plugin-sdk/setup-adapter-runtime,openclaw/plugin-sdk/setup-tools,openclaw/plugin-sdk/channel-pairing,openclaw/plugin-sdk/channel-contract,openclaw/plugin-sdk/channel-feedback,openclaw/plugin-sdk/channel-inbound,openclaw/plugin-sdk/channel-lifecycle,openclaw/plugin-sdk/channel-reply-pipeline,openclaw/plugin-sdk/command-auth,openclaw/plugin-sdk/secret-input, danopenclaw/plugin-sdk/webhook-ingressuntuk wiring setup/auth/balasan/webhook bersama.channel-inboundadalah rumah bersama untuk debounce, pencocokan mention, helper kebijakan mention inbound, pemformatan envelope, dan helper konteks envelope inbound.channel-setupadalah seam setup narrow optional-install.setup-runtimeadalah surface setup yang aman untuk runtime yang digunakan olehsetupEntry/ startup yang ditangguhkan, termasuk adaptor patch setup yang aman untuk impor.setup-adapter-runtimeadalah seam adaptor account-setup yang sadar env.setup-toolsadalah seam helper kecil untuk CLI/arsip/dokumen (formatCliCommand,detectBinary,extractArchive,resolveBrewExecutable,formatDocsLink,CONFIG_DIR). - Subpath domain seperti
openclaw/plugin-sdk/channel-config-helpers,openclaw/plugin-sdk/allow-from,openclaw/plugin-sdk/channel-config-schema,openclaw/plugin-sdk/telegram-command-config,openclaw/plugin-sdk/channel-policy,openclaw/plugin-sdk/approval-gateway-runtime,openclaw/plugin-sdk/approval-handler-adapter-runtime,openclaw/plugin-sdk/approval-handler-runtime,openclaw/plugin-sdk/approval-runtime,openclaw/plugin-sdk/config-runtime,openclaw/plugin-sdk/infra-runtime,openclaw/plugin-sdk/agent-runtime,openclaw/plugin-sdk/lazy-runtime,openclaw/plugin-sdk/reply-history,openclaw/plugin-sdk/routing,openclaw/plugin-sdk/status-helpers,openclaw/plugin-sdk/text-runtime,openclaw/plugin-sdk/runtime-store, danopenclaw/plugin-sdk/directory-runtimeuntuk helper runtime/konfigurasi bersama.telegram-command-configadalah seam publik sempit untuk normalisasi/validasi perintah kustom Telegram dan tetap tersedia meskipun surface kontrak Telegram bundled untuk sementara tidak tersedia.text-runtimeadalah seam teks/markdown/logging bersama, termasuk penghapusan teks yang terlihat oleh asisten, helper render/chunking markdown, helper redaksi, helper directive-tag, dan utilitas safe-text. - Seam channel yang spesifik persetujuan sebaiknya mengutamakan satu kontrak
approvalCapabilitypada plugin. Core kemudian membaca auth, pengiriman, render, native-routing, dan perilaku lazy native-handler persetujuan melalui satu kapabilitas itu alih-alih mencampurkan perilaku persetujuan ke field plugin yang tidak terkait. openclaw/plugin-sdk/channel-runtimesudah deprecated dan hanya tersisa sebagai shim kompatibilitas untuk plugin lama. Kode baru sebaiknya mengimpor primitif generik yang lebih sempit, dan kode repo tidak boleh menambahkan impor baru terhadap shim tersebut.- Internal extension bundled tetap privat. Plugin eksternal sebaiknya hanya menggunakan
subpath
openclaw/plugin-sdk/*. Kode core/test OpenClaw dapat menggunakan entry point publik repo di bawah root paket plugin sepertiindex.js,api.js,runtime-api.js,setup-entry.js, dan file yang discope sempit sepertilogin-qr-api.js. Jangan pernah mengimporsrc/*dari paket plugin dari core atau dari extension lain. - Pemisahan entry point repo:
<plugin-package-root>/api.jsadalah barrel helper/types,<plugin-package-root>/runtime-api.jsadalah barrel khusus runtime,<plugin-package-root>/index.jsadalah entry plugin bundled, dan<plugin-package-root>/setup-entry.jsadalah entry plugin setup. - Contoh provider bundled saat ini:
- Anthropic menggunakan
api.js/contract-api.jsuntuk helper stream Claude sepertiwrapAnthropicProviderStream, helper beta-header, dan parsingservice_tier. - OpenAI menggunakan
api.jsuntuk builder provider, helper model default, dan builder provider realtime. - OpenRouter menggunakan
api.jsuntuk builder provider-nya ditambah helper onboarding/config, sedangkanregister.runtime.jsmasih dapat mengekspor ulang helper generikplugin-sdk/provider-streamuntuk penggunaan lokal repo.
- Anthropic menggunakan
- Entry point publik yang dimuat melalui facade mengutamakan snapshot konfigurasi runtime aktif ketika ada, lalu fallback ke file konfigurasi yang di-resolve di disk ketika OpenClaw belum menyajikan snapshot runtime.
- Primitif generik bersama tetap menjadi kontrak SDK publik yang diutamakan. Sekumpulan kecil
seam helper bermerek channel bundled yang dicadangkan untuk kompatibilitas masih ada. Perlakukan itu sebagai
seam pemeliharaan bundled/kompatibilitas, bukan target impor pihak ketiga yang baru; kontrak lintas-channel baru tetap harus berada pada subpath generik
plugin-sdk/*atau barrelapi.js/runtime-api.jslokal plugin.
- Hindari barrel root
openclaw/plugin-sdkuntuk kode baru. - Utamakan primitif stabil yang sempit terlebih dahulu. Subpath setup/pairing/reply/
feedback/contract/inbound/threading/command/secret-input/webhook/infra/
allowlist/status/message-tool yang lebih baru adalah kontrak yang dituju untuk pekerjaan plugin
bundled dan eksternal yang baru.
Parsing/pencocokan target berada di
openclaw/plugin-sdk/channel-targets. Gerbang aksi pesan dan helper message-id reaksi berada diopenclaw/plugin-sdk/channel-actions. - Barrel helper khusus extension bundled tidak stabil secara default. Jika sebuah
helper hanya dibutuhkan oleh extension bundled, simpan di balik seam
api.jsatauruntime-api.jslokal extension tersebut alih-alih mempromosikannya keopenclaw/plugin-sdk/<extension>. - Seam helper bersama yang baru harus generik, bukan bermerek channel. Parsing target bersama
berada di
openclaw/plugin-sdk/channel-targets; internal khusus channel tetap berada di balik seamapi.jsatauruntime-api.jslokal plugin pemiliknya. - Subpath spesifik kapabilitas seperti
image-generation,media-understanding, danspeechada karena plugin bundled/native menggunakannya saat ini. Keberadaannya sendiri tidak berarti setiap helper yang diekspor adalah kontrak eksternal jangka panjang yang dibekukan.
Skema message tool
Plugin sebaiknya memiliki kontribusi skemadescribeMessageTool(...) khusus channel.
Pertahankan field khusus provider di plugin, bukan di core bersama.
Untuk fragmen skema portabel bersama, gunakan ulang helper generik yang diekspor melalui
openclaw/plugin-sdk/channel-actions:
createMessageToolButtonsSchema()untuk payload gaya grid tombolcreateMessageToolCardSchema()untuk payload kartu terstruktur
Resolusi target channel
Plugin channel sebaiknya memiliki semantik target khusus channel. Pertahankan host outbound bersama tetap generik dan gunakan surface adaptor pesan untuk aturan provider:messaging.inferTargetChatType({ to })memutuskan apakah target yang telah dinormalisasi harus diperlakukan sebagaidirect,group, atauchannelsebelum lookup direktori.messaging.targetResolver.looksLikeId(raw, normalized)memberi tahu core apakah suatu input harus langsung dilewatkan ke resolusi mirip-id alih-alih pencarian direktori.messaging.targetResolver.resolveTarget(...)adalah fallback plugin saat core memerlukan resolusi akhir milik provider setelah normalisasi atau setelah direktori tidak menemukan hasil.messaging.resolveOutboundSessionRoute(...)memiliki konstruksi rute sesi khusus provider setelah sebuah target di-resolve.
- Gunakan
inferTargetChatTypeuntuk keputusan kategori yang harus terjadi sebelum pencarian peer/group. - 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 chat id, thread id, JID, handle, dan room
id di dalam nilai
targetatau param khusus provider, bukan di field SDK generik.
Direktori berbasis konfigurasi
Plugin yang menurunkan entri direktori dari konfigurasi sebaiknya menjaga logika itu di plugin dan menggunakan ulang helper bersama dariopenclaw/plugin-sdk/directory-runtime.
Gunakan ini ketika sebuah channel memerlukan peer/group berbasis konfigurasi seperti:
- peer DM yang digerakkan allowlist
- peta channel/group yang dikonfigurasi
- fallback direktori statis yang dibatasi akun
directory-runtime hanya menangani operasi generik:
- penyaringan kueri
- penerapan batas
- helper deduplikasi/normalisasi
- membangun
ChannelDirectoryEntry[]
Katalog provider
Plugin provider dapat mendefinisikan katalog model untuk inferensi denganregisterProvider({ catalog: { run(...) { ... } } }).
catalog.run(...) mengembalikan bentuk yang sama yang ditulis OpenClaw ke dalam
models.providers:
{ provider }untuk satu entri provider{ providers }untuk beberapa entri provider
catalog ketika plugin memiliki model id khusus provider, default base URL,
atau metadata model yang dijaga oleh 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 ketika profil auth adapaired: provider yang mensintesis beberapa entri provider yang saling terkaitlate: pass terakhir, setelah provider implisit lainnya
discoverytetap berfungsi sebagai alias legacy- jika
catalogdandiscoverysama-sama didaftarkan, OpenClaw menggunakancatalog
Inspeksi channel read-only
Jika plugin Anda mendaftarkan sebuah channel, utamakan mengimplementasikanplugin.config.inspectAccount(cfg, accountId) bersama resolveAccount(...).
Mengapa:
resolveAccount(...)adalah jalur runtime. Jalur ini boleh mengasumsikan kredensial telah sepenuhnya dimaterialisasi dan dapat gagal cepat ketika secret yang diperlukan tidak ada.- Jalur perintah read-only seperti
openclaw status,openclaw status --all,openclaw channels status,openclaw channels resolve, dan alur perbaikan doctor/config tidak seharusnya perlu mematerialisasi kredensial runtime hanya untuk mendeskripsikan konfigurasi.
inspectAccount(...) yang direkomendasikan:
- Hanya kembalikan state akun yang deskriptif.
- Pertahankan
enableddanconfigured. - Sertakan field sumber/status kredensial jika relevan, seperti:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- Anda tidak perlu mengembalikan nilai token mentah hanya untuk melaporkan
ketersediaan read-only. Mengembalikan
tokenStatus: "available"(dan field sumber yang cocok) sudah cukup untuk perintah bergaya status. - Gunakan
configured_unavailableketika sebuah kredensial dikonfigurasi melalui SecretRef tetapi tidak tersedia pada jalur perintah saat ini.
Paket pack
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 paket akan
ditolak.
Catatan keamanan: openclaw plugins install menginstal dependensi plugin dengan
npm install --omit=dev --ignore-scripts (tanpa lifecycle script, tanpa dev dependency saat runtime). Pertahankan tree dependensi plugin
tetap “pure JS/TS” dan hindari paket yang memerlukan build postinstall.
Opsional: openclaw.setupEntry dapat menunjuk ke modul ringan khusus setup.
Ketika OpenClaw memerlukan surface setup untuk plugin channel yang dinonaktifkan, atau
ketika plugin channel diaktifkan tetapi masih belum dikonfigurasi, OpenClaw memuat setupEntry
alih-alih entri plugin penuh. Ini menjaga startup dan setup tetap lebih ringan
ketika entri plugin utama Anda juga mewiring tool, hook, atau kode
khusus runtime lainnya.
Opsional: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
dapat mengikutsertakan plugin channel ke jalur setupEntry yang sama selama fase
startup pre-listen gateway, bahkan ketika channel sudah dikonfigurasi.
Gunakan ini hanya ketika setupEntry sepenuhnya mencakup surface startup yang harus ada
sebelum gateway mulai mendengarkan. Dalam praktiknya, itu berarti entri setup
harus mendaftarkan setiap kapabilitas milik channel yang menjadi dependensi startup, seperti:
- pendaftaran channel itu sendiri
- rute HTTP apa pun yang harus tersedia sebelum gateway mulai mendengarkan
- metode gateway, tool, atau layanan apa pun yang harus ada selama jendela yang sama
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.* tanpa memuat entri plugin penuh.
Matrix adalah contoh bundled saat ini: plugin ini hanya memindahkan key auth/bootstrap ke akun
hasil promosi bernama ketika akun bernama sudah ada, dan plugin ini dapat mempertahankan
key default-account non-kanonis yang telah dikonfigurasi alih-alih selalu membuat
accounts.default.
Adaptor patch setup tersebut menjaga discovery contract-surface bundled tetap lazy. Waktu impor
tetap ringan; surface promosi hanya dimuat pada penggunaan pertama alih-alih
masuk kembali ke startup channel bundled saat impor modul.
Ketika surface startup tersebut mencakup metode RPC Gateway, pertahankan pada
prefiks spesifik plugin. Namespace admin core (config.*,
exec.approvals.*, wizard.*, update.*) tetap dicadangkan dan selalu di-resolve
ke operator.admin, bahkan jika 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 core tetap kosong.
Contoh:
openclaw.channel yang berguna di luar contoh minimal:
detailLabel: label sekunder untuk surface katalog/status yang lebih kayadocsLabel: override teks tautan untuk tautan dokumenpreferOver: id plugin/channel prioritas lebih rendah yang harus dikalahkan oleh entri katalog iniselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: kontrol copy surface pemilihanmarkdownCapable: menandai channel sebagai mampu markdown untuk keputusan pemformatan outboundexposure.configured: sembunyikan channel dari surface daftar channel yang dikonfigurasi ketika disetel kefalseexposure.setup: sembunyikan channel dari picker setup/konfigurasi interaktif ketika disetel kefalseexposure.docs: tandai channel sebagai internal/private untuk surface navigasi dokumenshowConfigured/showInSetup: alias legacy masih diterima demi kompatibilitas; utamakanexposurequickstartAllowFrom: ikutsertakan channel ke alurallowFromquickstart standarforceAccountBinding: wajibkan pengikatan akun eksplisit meskipun hanya ada satu akunpreferSessionLookupForAnnounceTarget: utamakan lookup sesi saat me-resolve 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 dengan koma/titik koma/PATH). Setiap file harus
berisi { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }. Parser juga menerima "packages" atau "plugins" sebagai alias legacy untuk key "entries".
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 ketika plugin Anda perlu mengganti atau memperluas pipeline konteks default
alih-alih hanya menambahkan pencarian memory atau hook.
compact()
dan delegasikan secara eksplisit:
Menambahkan kapabilitas baru
Ketika sebuah plugin memerlukan perilaku yang tidak sesuai dengan API saat ini, jangan melewati sistem plugin dengan akses privat ke internal. Tambahkan kapabilitas yang belum ada. Urutan yang direkomendasikan:- definisikan kontrak core Putuskan perilaku bersama apa yang harus dimiliki core: kebijakan, fallback, merge konfigurasi, lifecycle, semantik yang menghadap channel, dan bentuk helper runtime.
- tambahkan surface pendaftaran/runtime plugin yang bertipe
Perluas
OpenClawPluginApidan/atauapi.runtimedengan surface kapabilitas bertipe terkecil yang berguna. - hubungkan konsumen core + channel/fitur Plugin channel dan fitur harus mengonsumsi kapabilitas baru melalui core, bukan dengan langsung mengimpor implementasi vendor.
- daftarkan implementasi vendor Plugin vendor kemudian mendaftarkan backend mereka terhadap kapabilitas tersebut.
- tambahkan cakupan kontrak Tambahkan pengujian agar bentuk kepemilikan dan pendaftaran tetap eksplisit seiring waktu.
Checklist kapabilitas
Ketika Anda menambahkan kapabilitas baru, implementasinya biasanya harus menyentuh surface berikut secara bersama:- tipe kontrak core di
src/<capability>/types.ts - helper runner/runtime core di
src/<capability>/runtime.ts - surface pendaftaran API plugin di
src/plugins/types.ts - wiring registri plugin di
src/plugins/registry.ts - eksposur runtime plugin di
src/plugins/runtime/*ketika plugin fitur/channel perlu mengonsumsinya - helper capture/test di
src/test-utils/plugin-registration.ts - assertion kepemilikan/kontrak di
src/plugins/contracts/registry.ts - dokumen operator/plugin di
docs/
Templat kapabilitas
Pola minimal:- core memiliki kontrak kapabilitas + orkestrasi
- plugin vendor memiliki implementasi vendor
- plugin fitur/channel mengonsumsi helper runtime
- pengujian kontrak menjaga kepemilikan tetap eksplisit