對於公開能力模型、Plugin 形態,以及所有權/執行合約,請參閱 Plugin 架構。本頁是內部機制的參考:載入管線、登錄表、執行階段 hook、Gateway HTTP 路由、匯入路徑,以及 schema 表格。Documentation Index
Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
載入管線
啟動時,OpenClaw 大致會執行以下流程:- 探索候選 Plugin 根目錄
- 讀取原生或相容 bundle 資訊清單與套件中繼資料
- 拒絕不安全的候選項
- 正規化 Plugin 設定(
plugins.enabled、allow、deny、entries、slots、load.paths) - 決定每個候選項是否啟用
- 載入已啟用的原生模組:已建置的 bundled 模組使用原生載入器; 第三方本機原始碼 TypeScript 使用緊急 Jiti fallback
- 呼叫原生
register(api)hook,並將註冊收集到 Plugin 登錄表 - 將登錄表公開給命令/執行階段介面
activate 是 register 的舊版別名 — 載入器會解析目前存在的項目(def.register ?? def.activate),並在同一個時間點呼叫它。所有 bundled Plugin 都使用 register;新的 Plugin 請優先使用 register。資訊清單優先行為
資訊清單是控制平面的事實來源。OpenClaw 會使用它來:- 識別 Plugin
- 探索宣告的頻道/skills/設定 schema 或 bundle 能力
- 驗證
plugins.entries.<id>.config - 補充 Control UI 標籤/placeholder
- 顯示安裝/catalog 中繼資料
- 在不載入 Plugin 執行階段的情況下保留低成本 activation 與設定描述器
activation 與 setup 區塊會留在控制平面上。它們是 activation 規劃與設定探索的純中繼資料描述器;它們不會取代執行階段註冊、register(...) 或 setupEntry。
第一批即時 activation 消費者現在會使用資訊清單命令、頻道與 provider 提示,在更廣泛的登錄表實體化之前縮小 Plugin 載入範圍:
- CLI 載入會縮小到擁有所要求主要命令的 Plugin
- 頻道設定/Plugin 解析會縮小到擁有所要求頻道 id 的 Plugin
- 明確的 provider 設定/執行階段解析會縮小到擁有所要求 provider id 的 Plugin
- Gateway 啟動規劃會使用
activation.onStartup進行明確的啟動匯入與啟動選擇退出;沒有啟動中繼資料的 Plugin 只會透過較窄的 activation 觸發器載入
all 範圍的請求時間執行階段預載,仍會從設定、啟動規劃、已設定頻道、slot 與自動啟用規則推導出明確的有效 Plugin id 集合。如果該推導集合為空,OpenClaw 會載入空的執行階段登錄表,而不是擴大到每個可探索的 Plugin。
activation 規劃器同時公開供現有呼叫端使用的僅 ids API,以及供新診斷使用的 plan API。Plan 項目會回報 Plugin 被選取的原因,並將明確的 activation.* 規劃器提示,與資訊清單所有權 fallback(例如 providers、channels、commandAliases、setup.providers、contracts.tools 與 hook)分開。這個原因區分就是相容性邊界:現有 Plugin 中繼資料會持續運作,而新程式碼可以偵測廣泛提示或 fallback 行為,而不改變執行階段載入語意。
設定探索現在會優先使用描述器擁有的 id,例如 setup.providers 與 setup.cliBackends,以便在 fallback 到仍需要設定時間執行階段 hook 的 Plugin 的 setup-api 之前縮小候選 Plugin。Provider 設定清單會使用資訊清單 providerAuthChoices、由描述器推導的設定選項,以及安裝 catalog 中繼資料,而不載入 provider 執行階段。明確的 setup.requiresRuntime: false 是僅描述器的截斷點;省略的 requiresRuntime 會為了相容性保留舊版 setup-api fallback。如果多個已探索的 Plugin 宣告相同的正規化設定 provider 或 CLI backend id,設定查詢會拒絕模稜兩可的擁有者,而不是依賴探索順序。當設定執行階段確實執行時,登錄表診斷會回報 setup.providers / setup.cliBackends 與 setup-api 註冊的 provider 或 CLI backend 之間的漂移,但不會封鎖舊版 Plugin。
Plugin 快取邊界
OpenClaw 不會在時間窗後方快取 Plugin 探索結果或直接資訊清單登錄表資料。安裝、資訊清單編輯與載入路徑變更,必須在下一次明確中繼資料讀取或 snapshot 重建時變得可見。 資訊清單檔案 parser 可以保留有界的檔案簽章快取,其 key 由已開啟的資訊清單路徑、inode、大小與時間戳組成;該快取只會避免重新解析未變更的位元組,且不得快取探索、登錄表、擁有者或政策答案。 安全的中繼資料快速路徑是明確物件所有權,而不是隱藏快取。Gateway 啟動熱路徑應該將目前的PluginMetadataSnapshot、推導出的 PluginLookUpTable,或明確的資訊清單登錄表沿呼叫鏈傳遞。設定驗證、啟動自動啟用、Plugin bootstrap 與 provider 選取,都可以在那些物件代表目前設定與 Plugin inventory 時重用它們。設定查詢仍會按需重建資訊清單中繼資料,除非特定設定路徑收到明確的資訊清單登錄表;請將此保留為冷路徑 fallback,而不是新增隱藏查詢快取。當輸入變更時,請重建並取代 snapshot,而不是修改它或保留歷史副本。
作用中 Plugin 登錄表的 view 與 bundled 頻道 bootstrap helper 應該從目前的登錄表/根目錄重新計算。短生命週期的 map 可以在單次呼叫內用於去重工作或防止重入;它們不得變成程序中繼資料快取。
對於 Plugin 載入,持久快取層是執行階段載入。當程式碼或已安裝 artifact 確實被載入時,它可以重用載入器狀態,例如:
PluginLoaderCacheState與相容的作用中執行階段登錄表- 用於避免重複匯入相同執行階段介面的 jiti/模組快取與公開介面載入器快取
- 已安裝 Plugin artifact 的檔案系統快取
- 用於路徑正規化或重複項解析的短生命週期每次呼叫 map
- 探索結果
- 直接資訊清單登錄表
- 從已安裝 Plugin 索引重建的資訊清單登錄表
- provider 擁有者查詢、模型抑制、provider 政策,或公開 artifact 中繼資料
- 任何其他由資訊清單推導的答案,其中變更後的資訊清單、已安裝索引或載入路徑應該在下一次中繼資料讀取時可見
登錄表模型
已載入的 Plugin 不會直接修改任意核心全域變數。它們會註冊到中央 Plugin 登錄表。 登錄表會追蹤:- Plugin 記錄(身分、來源、origin、狀態、診斷)
- 工具
- 舊版 hook 與具型別 hook
- 頻道
- provider
- Gateway RPC handler
- HTTP 路由
- CLI registrar
- 背景服務
- Plugin 擁有的命令
- Plugin 模組 -> 登錄表註冊
- 核心執行階段 -> 登錄表消費
對話繫結 callback
繫結對話的 Plugin 可以在 approval 被解析時作出反應。 使用api.onConversationBindingResolved(...),在 bind 要求被核准或拒絕後接收 callback:
status:"approved"或"denied"decision:"allow-once"、"allow-always"或"deny"binding: 已核准要求的已解析繫結request: 原始要求摘要、detach 提示、sender id 與對話中繼資料
Provider 執行階段 hook
Provider Plugin 有三層:- 資訊清單中繼資料,用於低成本的執行階段前查詢:
setup.providers[].envVars、已棄用的相容性providerAuthEnvVars、providerAuthAliases、providerAuthChoices與channelEnvVars。 - 設定時間 hook:
catalog(舊版discovery)加上applyConfigDefaults。 - 執行階段 hook:40 多個選用 hook,涵蓋 auth、模型解析、 stream wrapping、thinking levels、replay policy 與 usage endpoints。請參閱 Hook 順序與用法 下方的完整清單。
setup.providers[].envVars。在棄用期間,相容性 adapter 仍會讀取已棄用的 providerAuthEnvVars,使用它的非 bundled Plugin 會收到資訊清單診斷。當某個 provider id 應該重用另一個 provider id 的 env vars、auth profiles、設定支援的 auth 與 API key onboarding 選項時,請使用資訊清單 providerAuthAliases。當 onboarding/auth-choice CLI 介面應該在不載入 provider 執行階段的情況下知道 provider 的 choice id、group labels 與簡單單旗標 auth wiring 時,請使用資訊清單 providerAuthChoices。Provider 執行階段 envVars 請保留給 operator-facing 提示,例如 onboarding labels 或 OAuth client-id/client-secret 設定變數。
當頻道有 env 驅動的 auth 或設定,且通用 shell-env fallback、config/status 檢查或設定 prompt 應該在不載入頻道執行階段的情況下看到它們時,請使用資訊清單 channelEnvVars。
Hook 順序與用法
對於模型/provider Plugin,OpenClaw 會大致按照此順序呼叫 hook。 「使用時機」欄是快速決策指南。 OpenClaw 不再呼叫的僅相容性 provider 欄位,例如ProviderPlugin.capabilities 與 suppressBuiltInModel,刻意未列於此處。
| # | Hook | 功能 | 使用時機 |
|---|---|---|---|
| 1 | catalog | 在產生 models.json 時,將提供者設定發布到 models.providers | 提供者擁有 catalog 或 base URL 預設值 |
| 2 | applyConfigDefaults | 在設定具體化期間套用提供者擁有的全域設定預設值 | 預設值取決於驗證模式、環境,或提供者模型家族語意 |
| — | (內建模型查詢) | OpenClaw 會先嘗試一般的註冊表/catalog 路徑 | (不是 Plugin hook) |
| 3 | normalizeModelId | 在查詢前正規化舊版或預覽版 model-id 別名 | 提供者在標準模型解析前擁有別名清理 |
| 4 | normalizeTransport | 在通用模型組裝前正規化提供者家族的 api / baseUrl | 提供者擁有同一傳輸家族中自訂提供者 ID 的傳輸清理 |
| 5 | normalizeConfig | 在 runtime/提供者解析前正規化 models.providers.<id> | 提供者需要應與 Plugin 一起存在的設定清理;內建 Google 家族輔助工具也會補強支援的 Google 設定項目 |
| 6 | applyNativeStreamingUsageCompat | 對設定提供者套用原生 streaming-usage 相容性重寫 | 提供者需要由端點驅動的原生串流用量中繼資料修正 |
| 7 | resolveConfigApiKey | 在載入 runtime 驗證前,為設定提供者解析 env-marker 驗證 | 提供者擁有由提供者管理的 env-marker API-key 解析;amazon-bedrock 也在這裡有內建 AWS env-marker 解析器 |
| 8 | resolveSyntheticAuth | 顯示本機/自架或設定支援的驗證,而不持久化明文 | 提供者可使用合成/本機憑證標記運作 |
| 9 | resolveExternalAuthProfiles | 疊加提供者擁有的外部驗證設定檔;CLI/app 擁有的憑證預設 persistence 為 runtime-only | 提供者重用外部驗證憑證,而不持久化複製的 refresh token;在 manifest 中宣告 contracts.externalAuthProviders |
| 10 | shouldDeferSyntheticProfileAuth | 將已儲存的合成設定檔 placeholder 排在 env/設定支援的驗證之後 | 提供者儲存不應取得優先權的合成 placeholder 設定檔 |
| 11 | resolveDynamicModel | 對尚未在本機註冊表中的提供者擁有模型 ID 提供同步 fallback | 提供者接受任意上游模型 ID |
| 12 | prepareDynamicModel | 非同步預熱,之後再次執行 resolveDynamicModel | 提供者在解析未知 ID 前需要網路中繼資料 |
| 13 | normalizeResolvedModel | 在嵌入式 runner 使用已解析模型前的最終重寫 | 提供者需要傳輸重寫,但仍使用核心傳輸 |
| 14 | contributeResolvedModelCompat | 為另一個相容傳輸後方的廠商模型貢獻相容性旗標 | 提供者可辨識 proxy 傳輸上的自身模型,而不接管該提供者 |
| 15 | normalizeToolSchemas | 在嵌入式 runner 看到工具 schema 前正規化它們 | 提供者需要傳輸家族 schema 清理 |
| 16 | inspectToolSchemas | 在正規化後顯示提供者擁有的 schema 診斷 | 提供者想要關鍵字警告,而不把提供者特定規則教給核心 |
| 17 | resolveReasoningOutputMode | 選擇原生或標記式 reasoning-output 契約 | 提供者需要標記式推理/最終輸出,而不是原生欄位 |
| 18 | prepareExtraParams | 在通用串流選項 wrapper 前正規化請求參數 | 提供者需要預設請求參數或每個提供者的參數清理 |
| 19 | createStreamFn | 以自訂傳輸完整取代一般串流路徑 | 提供者需要自訂 wire protocol,而不只是 wrapper |
| 20 | wrapStreamFn | 套用通用 wrapper 後的串流 wrapper | 提供者需要請求標頭/本文/模型相容性 wrapper,而不是自訂傳輸 |
| 21 | resolveTransportTurnState | 附加原生每回合傳輸標頭或中繼資料 | 提供者希望通用傳輸傳送提供者原生的回合識別 |
| 22 | resolveWebSocketSessionPolicy | 附加原生 WebSocket 標頭或 session cool-down 政策 | 提供者希望通用 WS 傳輸調整 session 標頭或 fallback 政策 |
| 23 | formatApiKey | 驗證設定檔格式化器:已儲存設定檔會成為 runtime apiKey 字串 | 提供者儲存額外驗證中繼資料,並需要自訂 runtime token 形狀 |
| 24 | refreshOAuth | 針對自訂 refresh 端點或 refresh-failure 政策的 OAuth refresh 覆寫 | 提供者不符合共用的 pi-ai refresher |
| 25 | buildAuthDoctorHint | OAuth refresh 失敗時附加的修復提示 | 提供者在 refresh 失敗後需要提供者擁有的驗證修復指引 |
| 26 | matchesContextOverflowError | 提供者擁有的 context-window overflow matcher | 提供者有通用啟發式會漏掉的原始 overflow 錯誤 |
| 27 | classifyFailoverReason | 提供者擁有的 failover 原因分類 | 提供者可將原始 API/傳輸錯誤對應到 rate-limit/overload 等 |
| 28 | isCacheTtlEligible | proxy/backhaul 提供者的 prompt-cache 政策 | 提供者需要 proxy 特定的 cache TTL gate |
| 29 | buildMissingAuthMessage | 取代通用 missing-auth 復原訊息 | 提供者需要提供者特定的 missing-auth 復原提示 |
| 30 | augmentModelCatalog | 在探索後附加的合成/最終 catalog 列 | 提供者需要在 models list 和選擇器中的合成 forward-compat 列 |
| 31 | resolveThinkingProfile | 模型特定的 /think 等級組、顯示標籤與預設值 | 提供者為選定模型公開自訂 thinking 階梯或二元標籤 |
| 32 | isBinaryThinking | 開/關推理切換相容性 hook | 提供者只公開二元 thinking 開/關 |
| 33 | supportsXHighThinking | xhigh 推理支援相容性 hook | 提供者只想在部分模型上啟用 xhigh |
| 34 | resolveDefaultThinkingLevel | 預設 /think 等級相容性 hook | 提供者擁有某個模型家族的預設 /think 政策 |
| 35 | isModernModelRef | 用於即時設定檔篩選器與 smoke 選擇的現代模型 matcher | 提供者擁有即時/smoke 偏好模型 matching |
| 36 | prepareRuntimeAuth | 在 inference 前,將已設定的憑證交換為實際 runtime token/key | 提供者需要 token exchange 或短效請求憑證 |
| 37 | resolveUsageAuth | 解析 /usage 與相關狀態介面的用量/帳務憑證 | 提供者需要自訂用量/配額權杖解析,或不同的用量憑證 |
| 38 | fetchUsageSnapshot | 在 auth 解析完成後,擷取並正規化提供者特定的用量/配額快照 | 提供者需要提供者特定的用量端點或酬載解析器 |
| 39 | createEmbeddingProvider | 為記憶/搜尋建構由提供者擁有的嵌入轉接器 | 記憶嵌入行為屬於提供者 Plugin |
| 40 | buildReplayPolicy | 傳回控制提供者逐字稿處理的重播政策 | 提供者需要自訂逐字稿政策(例如,移除 thinking 區塊) |
| 41 | sanitizeReplayHistory | 在通用逐字稿清理後重寫重播歷程 | 提供者需要超出共用 Compaction 輔助工具範圍的提供者特定重播重寫 |
| 42 | validateReplayTurns | 在嵌入式執行器執行前,進行最終重播回合驗證或重塑 | 提供者傳輸在通用清理後需要更嚴格的回合驗證 |
| 43 | onModelSelected | 執行由提供者擁有的選取後副作用 | 當模型變為作用中時,提供者需要遙測或由提供者擁有的狀態 |
normalizeModelId、normalizeTransport 和 normalizeConfig 會先檢查相符的 provider plugin,接著依序落到其他支援 hook 的 provider plugin,直到其中一個實際變更 model id 或 transport/config。這能讓 alias/compat provider shim 持續運作,而不需要呼叫端知道是哪個內建 plugin 擁有該 rewrite。如果沒有 provider hook rewrite 受支援的 Google-family config entry,內建的 Google config normalizer 仍會套用該相容性清理。
如果 provider 需要完全自訂的 wire protocol 或自訂 request executor,那屬於另一類 extension。這些 hook 適用於仍在 OpenClaw 一般 inference loop 上執行的 provider 行為。
Provider 範例
內建範例
內建 provider plugin 會結合上述 hook,以配合各 vendor 的 catalog、auth、thinking、replay 與 usage 需求。權威的 hook set 位於extensions/ 下各 plugin 中;本頁示範的是形狀,而不是鏡像複製清單。
直通式 catalog provider
直通式 catalog provider
OpenRouter、Kilocode、Z.AI、xAI 會註冊
catalog 加上
resolveDynamicModel / prepareDynamicModel,讓它們能在 OpenClaw 的靜態 catalog 之前呈現上游
model id。OAuth 與 usage endpoint provider
OAuth 與 usage endpoint provider
GitHub Copilot、Gemini CLI、ChatGPT Codex、MiniMax、Xiaomi、z.ai 會將
prepareRuntimeAuth 或 formatApiKey 搭配 resolveUsageAuth +
fetchUsageSnapshot,以擁有 token exchange 和 /usage 整合。Replay 與 transcript 清理 family
Replay 與 transcript 清理 family
共用的具名 family(
google-gemini、passthrough-gemini、
anthropic-by-model、hybrid-anthropic-openai)讓 provider 能透過
buildReplayPolicy 選用 transcript policy,而不是每個 plugin 都重新實作清理。僅 catalog 的 provider
僅 catalog 的 provider
byteplus、cloudflare-ai-gateway、huggingface、kimi-coding、nvidia、
qianfan、synthetic、together、venice、vercel-ai-gateway 和
volcengine 只註冊 catalog,並使用共用 inference loop。Anthropic 專用 stream helper
Anthropic 專用 stream helper
Beta header、
/fast / serviceTier 與 context1m 位於
Anthropic plugin 的公開 api.ts / contract-api.ts seam
(wrapAnthropicProviderStream、resolveAnthropicBetas、
resolveAnthropicFastMode、resolveAnthropicServiceTier),而不是在
通用 SDK 中。Runtime helper
Plugin 可以透過api.runtime 存取選定的核心 helper。以 TTS 為例:
textToSpeech會回傳一般核心 TTS output payload,供 file/voice-note surface 使用。- 使用核心
messages.ttsconfiguration 和 provider selection。 - 回傳 PCM audio buffer + sample rate。Plugin 必須為 provider 重新取樣/編碼。
listVoices依 provider 而定是 optional。可用於 vendor 擁有的 voice picker 或 setup flow。- Voice listing 可以包含更豐富的 metadata,例如 locale、gender 與 personality tag,以供 provider-aware picker 使用。
- OpenAI 和 ElevenLabs 目前支援 telephony。Microsoft 不支援。
api.registerSpeechProvider(...) 註冊 speech provider。
- 將 TTS policy、fallback 和 reply delivery 保留在核心。
- 使用 speech provider 處理 vendor 擁有的 synthesis 行為。
- 舊版 Microsoft
edgeinput 會 normalize 為microsoftprovider id。 - 偏好的 ownership model 是以公司為導向:一個 vendor plugin 可以在 OpenClaw 新增這些 capability contract 時,擁有 text、speech、image 與未來的 media provider。
- 將 orchestration、fallback、config 與 channel wiring 保留在核心。
- 將 vendor 行為保留在 provider plugin。
- Additive expansion 應維持 typed:新的 optional method、新的 optional result field、新的 optional capability。
- Video generation 已遵循相同模式:
- 核心擁有 capability contract 和 runtime helper
- vendor plugin 註冊
api.registerVideoGenerationProvider(...) - feature/channel plugin 使用
api.runtime.videoGeneration.*
api.runtime.mediaUnderstanding.*是 image/audio/video understanding 偏好的共用 surface。extractStructuredWithModel(...)是面向 plugin 的 seam,用於 bounded provider-owned image-first extraction。至少包含一個 image input; text input 是補充 context。 product plugin 擁有其 route 與 schema,而 OpenClaw 擁有 provider/runtime boundary。- 使用核心 media-understanding audio configuration(
tools.media.audio)和 provider fallback order。 - 當沒有產生 transcription output 時(例如 skipped/unsupported input),回傳
{ text: undefined }。 api.runtime.stt.transcribeAudioFile(...)仍保留為 compatibility alias。
api.runtime.subagent 啟動 background subagent run:
provider和model是每次 run 的 optional override,不是 persistent session change。- OpenClaw 只會對受信任的 caller 採用這些 override field。
- 對於 plugin-owned fallback run,operator 必須以
plugins.entries.<id>.subagent.allowModelOverride: true選用。 - 使用
plugins.entries.<id>.subagent.allowedModels將受信任 plugin 限制到特定 canonicalprovider/modeltarget,或使用"*"明確允許任何 target。 - Untrusted plugin subagent run 仍可運作,但 override request 會被拒絕,而不是 silently falling back。
- Plugin 建立的 subagent session 會以建立它的 plugin id 標記。Fallback
api.runtime.subagent.deleteSession(...)只能刪除這些 owned session;任意 session deletion 仍需要 admin-scoped Gateway request。
api.registerWebSearchProvider(...) 註冊 web-search provider。
注意事項:
- 將 provider selection、credential resolution 與 shared request semantics 保留在核心。
- 使用 web-search provider 處理 vendor-specific search transport。
api.runtime.webSearch.*是需要 search 行為但不想依賴 agent tool wrapper 的 feature/channel plugin 偏好的共用 surface。
api.runtime.imageGeneration
generate(...):使用 configured image-generation provider chain 產生 image。listProviders(...):列出可用的 image-generation provider 及其 capability。
Gateway HTTP route
Plugin 可以透過api.registerHttpRoute(...) 暴露 HTTP endpoint。
path:Gateway HTTP server 下的 route path。auth:必填。使用"gateway"要求一般 Gateway auth,或使用"plugin"進行 plugin-managed auth/webhook verification。match:optional。"exact"(default)或"prefix"。replaceExisting:optional。允許同一個 plugin 取代自己的既有 route registration。handler:當 route 已處理 request 時回傳true。
api.registerHttpHandler(...)已移除,且會造成 Plugin 載入錯誤。請改用api.registerHttpRoute(...)。- Plugin 路由必須明確宣告
auth。 - 除非設定
replaceExisting: true,否則會拒絕完全相同的path + match衝突,而且一個 Plugin 不能取代另一個 Plugin 的路由。 - 會拒絕具有不同
auth層級的重疊路由。請只在相同的 auth 層級上保留exact/prefix後援鏈。 auth: "plugin"路由不會自動收到操作者執行階段範圍。這些路由是供 Plugin 管理的 Webhook/簽章驗證使用,不是供具特權的 Gateway 輔助呼叫使用。auth: "gateway"路由會在 Gateway 請求執行階段範圍內執行,但該範圍刻意保守:- 共用密鑰 bearer auth(
gateway.auth.mode = "token"/"password")會讓 Plugin 路由執行階段範圍固定在operator.write,即使呼叫者送出x-openclaw-scopes也是如此 - 受信任、帶有身分的 HTTP 模式(例如
trusted-proxy,或私有入口上的gateway.auth.mode = "none")只有在標頭明確存在時,才會採用x-openclaw-scopes - 如果這些帶有身分的 Plugin 路由請求缺少
x-openclaw-scopes,執行階段範圍會退回operator.write
- 共用密鑰 bearer auth(
- 實務規則:不要假設 gateway-auth Plugin 路由是隱含的管理員介面。如果你的路由需要僅限管理員的行為,請要求帶有身分的 auth 模式,並記錄明確的
x-openclaw-scopes標頭合約。
Plugin SDK 匯入路徑
撰寫新 Plugin 時,請使用較窄的 SDK 子路徑,而不是單體的openclaw/plugin-sdk 根
barrel。核心子路徑:
| 子路徑 | 用途 |
|---|---|
openclaw/plugin-sdk/plugin-entry | Plugin 註冊基元 |
openclaw/plugin-sdk/channel-core | 通道進入點/建置輔助工具 |
openclaw/plugin-sdk/core | 通用共用輔助工具與總括合約 |
openclaw/plugin-sdk/config-schema | 根 openclaw.json Zod 結構描述(OpenClawSchema) |
channel-setup,
setup-runtime, setup-tools, channel-pairing,
channel-contract, channel-feedback, channel-inbound, channel-lifecycle,
channel-reply-pipeline, command-auth, secret-input, webhook-ingress,
channel-targets 和 channel-actions。核准行為應整合到單一
approvalCapability 合約上,而不是混用無關的 Plugin 欄位。
請參閱通道 Plugin。
執行階段與設定輔助工具位於相符且聚焦的 *-runtime 子路徑下
(approval-runtime, agent-runtime, lazy-runtime, directory-runtime,
text-runtime, runtime-store, system-event-runtime, heartbeat-runtime,
channel-activity-runtime 等)。請優先使用 config-contracts,
plugin-config-runtime, runtime-config-snapshot 和 config-mutation,
而不是寬泛的 config-runtime 相容性 barrel。
openclaw/plugin-sdk/channel-runtime, openclaw/plugin-sdk/config-runtime,
和 openclaw/plugin-sdk/infra-runtime 是提供給舊版 Plugin 的已棄用相容性 shim。
新程式碼應改為匯入較窄的通用基元。index.js— 隨附 Plugin 進入點api.js— 輔助工具/型別 barrelruntime-api.js— 僅限執行階段的 barrelsetup-entry.js— 設定 Plugin 進入點
openclaw/plugin-sdk/* 子路徑。絕不要從核心或另一個 Plugin
匯入另一個 Plugin 套件的 src/*。透過 facade 載入的進入點會在存在作用中的執行階段設定快照時優先使用它,
然後才退回磁碟上的已解析設定檔。
能力專用子路徑(例如 image-generation, media-understanding,
和 speech)之所以存在,是因為隨附 Plugin 目前使用它們。它們不會自動成為長期凍結的外部合約 — 依賴它們時,請查看相關的 SDK
參考頁面。
訊息工具結構描述
Plugin 應擁有通道專用的describeMessageTool(...) 結構描述貢獻,
用於反應、已讀和投票等非訊息基元。共用傳送呈現應使用通用的 MessagePresentation 合約,
而不是提供者原生的按鈕、元件、區塊或卡片欄位。
請參閱訊息呈現,了解合約、
後援規則、提供者對應和 Plugin 作者檢查清單。
具備傳送能力的 Plugin 會透過訊息能力宣告它們可以呈現的內容:
presentation用於語意呈現區塊(text,context,divider,buttons,select)delivery-pin用於釘選傳送請求
通道目標解析
通道 Plugin 應擁有通道專用的目標語意。請讓共用傳出主機保持通用, 並使用訊息傳遞配接器介面處理提供者規則:messaging.inferTargetChatType({ to })會在目錄查找前決定正規化目標 應被視為direct、group還是channel。messaging.targetResolver.looksLikeId(raw, normalized)會告訴核心某個輸入 是否應略過目錄搜尋,直接進入類似 ID 的解析。messaging.targetResolver.resolveTarget(...)是核心在正規化後或目錄未命中後, 需要最終由提供者擁有的解析時使用的 Plugin 後援。messaging.resolveOutboundSessionRoute(...)會在目標解析後,負責提供者專用的工作階段 路由建構。
- 使用
inferTargetChatType處理應在搜尋對等端/群組前發生的分類決策。 - 使用
looksLikeId進行「將此視為明確/原生目標 ID」檢查。 - 使用
resolveTarget作為提供者專用正規化後援,而不是用於寬泛的目錄搜尋。 - 將提供者原生 ID(例如聊天 ID、執行緒 ID、JID、控制代碼和房間 ID)保留在
target值或提供者專用參數中, 不要放在通用 SDK 欄位中。
由設定支援的目錄
從設定衍生目錄項目的 Plugin,應將該邏輯保留在 Plugin 內,並重複使用openclaw/plugin-sdk/directory-runtime 的共用輔助工具。
當通道需要由設定支援的對等端/群組時,請使用此方式,例如:
- 由允許清單驅動的 DM 對等端
- 已設定的通道/群組對應
- 以帳號為範圍的靜態目錄後援
directory-runtime 中的共用輔助工具只處理通用操作:
- 查詢篩選
- 套用限制
- 去重/正規化輔助工具
- 建立
ChannelDirectoryEntry[]
提供者目錄
提供者 Plugin 可透過registerProvider({ catalog: { run(...) { ... } } }) 定義推論用的模型目錄。
catalog.run(...) 會回傳與 OpenClaw 寫入
models.providers 相同的形狀:
{ provider }用於單一提供者項目{ providers }用於多個提供者項目
catalog。
catalog.order 控制 Plugin 目錄相對於 OpenClaw
內建隱含提供者的合併時機:
simple:普通 API 金鑰或由環境驅動的提供者profile:當 auth 設定檔存在時出現的提供者paired:合成多個相關提供者項目的提供者late:最後一道處理,在其他隱含提供者之後
api.registerModelCatalogProvider({ provider, kinds, staticCatalog, liveCatalog }) 發布唯讀模型列。這是清單/說明/選擇器介面的前進路徑,並支援
text, image_generation, video_generation 和 music_generation 列。
提供者 Plugin 仍擁有即時端點呼叫、權杖交換和供應商
回應對應;核心擁有共用列形狀、來源標籤和媒體工具
說明格式。媒體生成提供者註冊會自動從 defaultModel, models 和 capabilities
合成靜態目錄列。
相容性:
discovery仍可作為舊版別名運作,但會發出棄用警告- 如果同時註冊
catalog和discovery,OpenClaw 會使用catalog augmentModelCatalog已棄用;隨附提供者應透過registerModelCatalogProvider發布 補充列
唯讀通道檢查
如果你的 Plugin 註冊通道,建議在resolveAccount(...) 旁實作
plugin.config.inspectAccount(cfg, accountId)。
原因:
resolveAccount(...)是執行階段路徑。它可以假設認證資料 已完整具體化,並且可在缺少必要秘密時快速失敗。- 唯讀命令路徑,例如
openclaw status,openclaw status --all,openclaw channels status,openclaw channels resolve,以及 doctor/設定 修復流程,不應只是為了描述設定就需要具體化執行階段認證資料。
inspectAccount(...) 行為:
- 只回傳描述性的帳號狀態。
- 保留
enabled和configured。 - 視需要包含認證資料來源/狀態欄位,例如:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- 你不需要為了回報唯讀可用性而回傳原始權杖值。
回傳
tokenStatus: "available"(以及相符的來源欄位)就足以供狀態類命令使用。 - 當認證資料透過 SecretRef 設定,但在目前命令路徑中不可用時,請使用
configured_unavailable。
套件包
Plugin 目錄可以包含帶有openclaw.extensions 的 package.json:
name/<fileBase>。
如果你的 Plugin 匯入 npm 相依套件,請在該目錄中安裝它們,讓
node_modules 可用(npm install / pnpm install)。
安全防護:每個 openclaw.extensions 項目在符號連結解析後,都必須保留在 Plugin
目錄內。逃出套件目錄的項目會被拒絕。
安全注意事項:openclaw plugins install 會使用專案本機的
npm install --omit=dev --ignore-scripts 安裝 Plugin 相依套件(無生命週期指令碼,
執行階段無開發相依套件),並忽略繼承的全域 npm 安裝設定。
請保持 Plugin 相依樹為「純 JS/TS」,並避免需要
postinstall 建置的套件。
選用:openclaw.setupEntry 可指向輕量的僅限設定模組。
當 OpenClaw 需要已停用通道 Plugin 的設定介面,或
當通道 Plugin 已啟用但尚未設定時,它會載入 setupEntry
而不是完整的 Plugin 進入點。當你的主要 Plugin 進入點也連接工具、hook 或其他僅限執行階段的
程式碼時,這可讓啟動和設定更輕量。
選用:openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
可讓通道 Plugin 在 gateway 的
listen 前啟動階段選擇使用相同的 setupEntry 路徑,即使該通道已完成設定也是如此。
只有在 setupEntry 完全涵蓋 Gateway 開始監聽前必須存在的啟動介面時,才使用這個選項。實務上,這表示 setup entry 必須註冊啟動所依賴的每個通道所擁有的能力,例如:
- 通道註冊本身
- Gateway 開始監聽前必須可用的任何 HTTP 路由
- 同一時間窗口內必須存在的任何 Gateway 方法、工具或服務
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.* 時,會使用該介面。Matrix 是目前的內建範例:當具名帳號已存在時,它只會將 auth/bootstrap 鍵移入具名提升帳號,而且可以保留已設定的非標準預設帳號鍵,而不是一律建立 accounts.default。
這些 setup patch adapter 讓內建契約介面探索保持延遲。匯入時間保持輕量;提升介面只會在首次使用時載入,而不是在模組匯入時重新進入內建通道啟動流程。
當這些啟動介面包含 Gateway RPC 方法時,請讓它們使用 Plugin 專用前綴。核心 admin 命名空間(config.*、exec.approvals.*、wizard.*、update.*)仍然保留,且一律解析為 operator.admin,即使 Plugin 要求較窄的範圍也一樣。
範例:
通道目錄中繼資料
通道 Plugin 可以透過openclaw.channel 宣告 setup/discovery 中繼資料,並透過 openclaw.install 宣告安裝提示。這讓核心目錄不需要內建資料。
範例:
openclaw.channel 欄位包括:
detailLabel:用於更豐富目錄/狀態介面的次要標籤docsLabel:覆寫文件連結文字preferOver:此目錄項目應優先於其上的較低優先權 Plugin/通道 IDselectionDocsPrefix、selectionDocsOmitLabel、selectionExtras:選擇介面的文字控制markdownCapable:將通道標示為支援 markdown,以供輸出格式決策使用exposure.configured:設定為false時,從已設定通道清單介面中隱藏該通道exposure.setup:設定為false時,從互動式 setup/configure 選擇器中隱藏該通道exposure.docs:將通道標示為文件導覽介面的內部/私有項目showConfigured/showInSetup:為相容性仍接受的舊版別名;建議使用exposurequickstartAllowFrom:讓通道加入標準 quickstartallowFrom流程forceAccountBinding:即使只有一個帳號存在,也要求明確帳號繫結preferSessionLookupForAnnounceTarget:解析 announce target 時優先使用 session lookup
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
OPENCLAW_PLUGIN_CATALOG_PATHS(或 OPENCLAW_MPM_CATALOG_PATHS)指向一個或多個 JSON 檔案(以逗號/分號/PATH 分隔)。每個檔案都應包含 { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }。解析器也接受 "packages" 或 "plugins" 作為 "entries" 鍵的舊版別名。
產生的通道目錄項目與 provider 安裝目錄項目,會在原始 openclaw.install 區塊旁公開標準化的安裝來源事實。標準化事實會識別 npm spec 是精確版本還是浮動選擇器、預期完整性中繼資料是否存在,以及本機來源路徑是否也可用。當目錄/套件身分已知時,如果解析出的 npm 套件名稱偏離該身分,標準化事實會發出警告。當 defaultChoice 無效或指向不可用的來源,以及 npm 完整性中繼資料存在但沒有有效 npm 來源時,它們也會發出警告。消費者應將 installSource 視為加成的選用欄位,因此手工建立的項目與目錄 shim 不必合成它。
這讓 onboarding 與診斷能在不匯入 Plugin 執行階段的情況下,說明來源平面的狀態。
官方外部 npm 項目應優先使用精確的 npmSpec 加上 expectedIntegrity。裸套件名稱與 dist-tags 仍可為相容性運作,但它們會顯示來源平面警告,讓目錄可以朝固定版本、完整性檢查的安裝移動,而不破壞既有 Plugin。
當 onboarding 從本機目錄路徑安裝時,它會記錄一個受管理的 Plugin 索引項目,其中包含 source: "path",並在可能時包含相對於工作區的 sourcePath。絕對的操作載入路徑仍保留在 plugins.load.paths;安裝記錄會避免將本機工作站路徑重複寫入長期設定。這讓本機開發安裝能被來源平面診斷看見,而不增加第二個原始檔案系統路徑揭露介面。持久化的 plugins/installs.json Plugin 索引是安裝來源的真實來源,且可在不載入 Plugin 執行階段模組的情況下重新整理。即使 Plugin manifest 遺失或無效,其 installRecords map 仍是持久的;其 plugins 陣列則是可重建的 manifest 檢視。
Context engine Plugin
Context engine Plugin 擁有 ingest、assembly 與 Compaction 的 session context 編排。使用api.registerContextEngine(id, factory) 從你的 Plugin 註冊它們,然後使用 plugins.slots.contextEngine 選擇作用中的 engine。
當你的 Plugin 需要取代或擴充預設 context pipeline,而不只是加入 memory search 或 hook 時,請使用此方式。
ctx 會公開選用的 config、agentDir 與 workspaceDir 值,以供建構期間初始化使用。
如果你的 engine 不擁有 Compaction 演算法,請保留 compact() 實作,並明確委派它:
新增能力
當 Plugin 需要目前 API 不適合的行為時,不要透過私有 reach-in 繞過 Plugin 系統。請加入缺少的能力。 建議順序:- 定義核心契約 決定核心應擁有哪些共享行為:政策、fallback、設定合併、生命週期、面向通道的語意,以及執行階段輔助工具形狀。
- 加入型別化的 Plugin 註冊/執行階段介面
以最小實用的型別化能力介面擴充
OpenClawPluginApi和/或api.runtime。 - 串接核心 + 通道/功能消費者 通道與功能 Plugin 應透過核心消費新能力,而不是直接匯入 vendor 實作。
- 註冊 vendor 實作 然後由 vendor Plugin 針對該能力註冊其後端。
- 加入契約覆蓋 加入測試,讓所有權與註冊形狀能隨時間保持明確。
能力檢查清單
新增能力時,實作通常應一起觸及這些介面:src/<capability>/types.ts中的核心契約型別src/<capability>/runtime.ts中的核心 runner/執行階段輔助工具src/plugins/types.ts中的 Plugin API 註冊介面src/plugins/registry.ts中的 Plugin registry 串接- 當功能/通道 Plugin 需要消費它時,
src/plugins/runtime/*中的 Plugin 執行階段公開 src/test-utils/plugin-registration.ts中的 capture/test 輔助工具src/plugins/contracts/registry.ts中的所有權/契約斷言docs/中的 operator/Plugin 文件
能力範本
最小模式:- 核心擁有能力契約 + 編排
- vendor Plugin 擁有 vendor 實作
- 功能/通道 Plugin 消費執行階段輔助工具
- 契約測試讓所有權保持明確
相關
- Plugin 架構 — 公開能力模型與形狀
- Plugin SDK subpaths
- Plugin SDK setup
- 建置 Plugin