ロードパイプライン
起動時、OpenClaw はおおよそ次の処理を行います。- 候補 Plugin ルートを検出する
- ネイティブまたは互換バンドルのマニフェストとパッケージメタデータを読み取る
- 安全でない候補を拒否する
- Plugin 設定(
plugins.enabled、allow、deny、entries,slots、load.paths)を正規化する - 各候補の有効化を判断する
- 有効化されたネイティブモジュールをロードする: ビルド済みのバンドルモジュールはネイティブローダーを使用し、 サードパーティのローカルソース TypeScript は緊急用の Jiti フォールバックを使用する
- ネイティブの
register(api)フックを呼び出し、登録内容を Plugin レジストリに収集する - コマンド/ランタイム面にレジストリを公開する
activate は register のレガシーエイリアスです。ローダーは存在する方(def.register ?? def.activate)を解決し、同じ時点で呼び出します。すべてのバンドル済み Plugin は register を使用します。新しい Plugin では register を優先してください。- 解決されたエントリが Plugin ルートの外へ出る
- パス(またはそのルートディレクトリ)が world-writable である
- 非バンドル Plugin で、パスの所有者が現在の uid(または root)と一致しない
chmod 修復を試みます(npm/global インストールではパッケージディレクトリが 0777 で出荷されることがあります)。所有者チェックはバンドル由来の場合は完全にスキップされます。
ブロックされた候補でも、Plugin id が分かっている場合(それ以外なら拒否されるディレクトリ内のマニフェストから解決された id を含む)は、出力される診断にその Plugin id が含まれます。そのため、その id を参照する設定では、無関係な「不明な Plugin」エラーではなく、パス安全性警告に紐づいたブロック済み Plugin として扱われます。
マニフェスト優先の動作
マニフェストは制御プレーンの信頼できる情報源です。OpenClaw はこれを使って次を行います。- Plugin を識別する
- 宣言されたチャンネル/Skills/設定スキーマまたはバンドル capability を検出する
plugins.entries.<id>.configを検証する- Control UI のラベル/プレースホルダーを補強する
- インストール/カタログメタデータを表示する
- Plugin ランタイムをロードせずに、軽量な activation と setup 記述子を保持する
activation ブロックと setup ブロックは制御プレーンに留まります。これらは activation 計画と setup 検出のためのメタデータ専用記述子です。ランタイム登録、register(...)、setupEntry を置き換えるものではありません。ライブ activation の利用側は、マニフェストのコマンド、チャンネル、プロバイダーのヒントを使用して、より広いレジストリ具体化の前に Plugin ロードを絞り込みます。
- CLI ロードは、要求されたプライマリコマンドを所有する Plugin に絞り込む
- チャンネル setup/Plugin 解決は、要求されたチャンネル id を所有する Plugin に絞り込む
- 明示的なプロバイダー setup/ランタイム解決は、要求されたプロバイダー id を所有する Plugin に絞り込む
- Gateway 起動計画は、明示的な起動時インポートに
activation.onStartupを使用する。起動メタデータのない Plugin は、より狭い activation トリガーを通じてのみロードされる
activation.* ヒントとマニフェスト所有権フォールバックを分離します。
理由(activation.* ヒント由来) | 理由(マニフェスト所有権由来) |
|---|---|
activation-agent-harness-hint | — |
activation-capability-hint | — |
activation-channel-hint | manifest-channel-owner (channels) |
activation-command-hint | manifest-command-alias (commandAliases) |
activation-provider-hint | manifest-provider-owner (providers), manifest-setup-provider-owner (setup.providers) |
activation-route-hint | — |
| —(フックトリガーにはヒントのバリアントがない) | manifest-hook-owner (hooks), manifest-tool-contract (contracts.tools) |
all スコープを要求するリクエスト時ランタイムプリロードでも、設定、起動計画、設定済みチャンネル、slots、自動有効化ルールから、明示的な有効 Plugin id セットを導出します(src/plugins/effective-plugin-ids.ts の resolveEffectivePluginIds)。その導出されたセットが空の場合、OpenClaw は検出可能なすべての Plugin に広げるのではなく、スコープを空のままにします。
Setup 検出は、setup.providers や setup.cliBackends などの記述子所有 id を優先し、setup-api にフォールバックする前に候補 Plugin を絞り込みます。これは setup 時ランタイムフックをまだ必要とする Plugin 向けです。プロバイダー setup リストは、プロバイダーランタイムをロードせずに、マニフェストの providerAuthChoices、記述子から導出された setup choices、インストールカタログメタデータを使用します。明示的な setup.requiresRuntime: false は記述子のみの打ち切りです。requiresRuntime が省略されている場合は、互換性のためにレガシーの setup-api フォールバックを維持します。検出された複数の Plugin が同じ正規化済み setup プロバイダーまたは CLI backend id を主張する場合、setup lookup は検出順に依存せず、曖昧な所有者を拒否します。setup ランタイムが実行される場合、レジストリ診断は、setup.providers / setup.cliBackends と、setup-api によって実際に登録されたプロバイダーまたは CLI backend の不一致を報告しますが、レガシー Plugin はブロックしません。
Plugin キャッシュ境界
OpenClaw は、Plugin 検出結果や直接のマニフェストレジストリデータを、壁時計時間のウィンドウの背後にキャッシュしません。インストール、マニフェスト編集、ロードパス変更は、次の明示的なメタデータ読み取りまたはスナップショット再構築で見える必要があります。マニフェストファイルパーサーは、開かれたマニフェストパスに device/inode、size、mtime/ctime を加えたものをキーとする、有界のファイルシグネチャキャッシュを保持します。このキャッシュは変更されていないバイト列の再パースを避けるだけであり、検出、レジストリ、所有者、ポリシーの回答をキャッシュしてはなりません。 安全なメタデータ高速パスは、隠れたキャッシュではなく、明示的なオブジェクト所有権です。Gateway 起動のホットパスでは、現在のPluginMetadataSnapshot、導出された PluginLookUpTable、または明示的なマニフェストレジストリを呼び出しチェーンで渡すべきです。設定検証、起動時自動有効化、Plugin ブートストラップ、プロバイダー選択は、それらのオブジェクトが現在の設定と Plugin インベントリを表している間は再利用できます。Setup lookup は、特定の setup パスが明示的なマニフェストレジストリを受け取らない限り、依然として必要に応じてマニフェストメタデータを再構築します。隠れた lookup キャッシュを追加するのではなく、これをコールドパスフォールバックとして維持してください。入力が変わったら、スナップショットを変更したり履歴コピーを保持したりするのではなく、再構築して置き換えます。アクティブな Plugin レジストリ上のビューと、バンドル済みチャンネルブートストラップヘルパーは、現在のレジストリ/ルートから再計算すべきです。短命のマップは、1 回の呼び出し内で作業を重複排除したり再入を防いだりする用途なら問題ありません。ただし、プロセスメタデータキャッシュになってはなりません。
Plugin ロードにおいて、永続キャッシュ層はランタイムロードです。コードやインストール済みアーティファクトが実際にロードされる場合、次のようなローダー状態を再利用できます。
PluginLoaderCacheStateと互換性のあるアクティブランタイムレジストリ- 同じランタイム面を繰り返しインポートするのを避けるために使われる jiti/module キャッシュと public-surface ローダーキャッシュ
- インストール済み Plugin アーティファクト用のファイルシステムキャッシュ
- パス正規化や重複解決用の短命な呼び出し単位マップ
- 検出結果
- 直接のマニフェストレジストリ
- インストール済み Plugin インデックスから再構築されたマニフェストレジストリ
- プロバイダー所有者 lookup、モデル抑制、プロバイダーポリシー、public-artifact メタデータ
- 変更されたマニフェスト、インストール済みインデックス、ロードパスが次のメタデータ読み取りで見えるべき、その他のマニフェスト由来の回答
レジストリモデル
ロード済み Plugin は、任意のコアグローバルを直接変更しません。中央の Plugin レジストリ(src/plugins/registry-types.ts の PluginRegistry)に登録します。このレジストリは Plugin レコード(identity、source、origin、status、diagnostics)に加え、すべての capability 用の配列を追跡します。対象には、tools、レガシーフックと型付きフック、channels、providers、gateway RPC handlers、HTTP routes、CLI registrars、background services、Plugin 所有 commands、さらに多数の型付きプロバイダーファミリー(speech、embeddings、image/video/music generation、web fetch/search、agent harnesses、session actions など)が含まれます。
その後、コア機能は Plugin モジュールと直接やり取りするのではなく、そのレジストリから読み取ります。これによりロードは一方向に保たれます。
- Plugin モジュール -> レジストリ登録
- コアランタイム -> レジストリ消費
会話バインディングコールバック
会話をバインドする Plugin は、承認が解決されたときに反応できます。api.onConversationBindingResolved(...) を使用すると、バインドリクエストが承認または拒否された後にコールバックを受け取れます。
status:"approved"または"denied"decision:"allow-once"、"allow-always"、または"deny"binding: 承認されたリクエストの解決済みバインディングrequest: 元のリクエスト概要、detach hint、sender id、会話メタデータ
プロバイダーランタイムフック
プロバイダー Plugin には 3 つのレイヤーがあります。- 安価なランタイム前 lookup のためのマニフェストメタデータ:
setup.providers[].envVars、非推奨の互換性providerAuthEnvVars、providerAuthAliases、providerAuthChoices、channelEnvVars。 - 設定時フック:
catalog(レガシーdiscovery)とapplyConfigDefaults。 - ランタイムフック: 認証、モデル解決、ストリームラップ、thinking levels、replay policy、使用量エンドポイントをカバーする 40 個以上の任意フック。フックの順序と使い方を参照してください。
setup.providers[].envVars を使用します。非推奨の providerAuthEnvVars は、非推奨期間中は互換性アダプターによって引き続き読み取られ、それを使用する非バンドル Plugin はマニフェスト診断を受け取ります。あるプロバイダー ID が別のプロバイダー ID の環境変数、認証プロファイル、設定ベースの認証、API キーのオンボーディング選択を再利用する必要がある場合は、マニフェストの providerAuthAliases を使用します。オンボーディング/認証選択 CLI サーフェスが、プロバイダーランタイムを読み込まずにプロバイダーの選択 ID、グループラベル、単純な単一フラグ認証の配線を知る必要がある場合は、マニフェストの providerAuthChoices を使用します。オンボーディングラベルや OAuth クライアント ID/クライアントシークレット設定変数など、運用者向けのヒントには、プロバイダーランタイムの envVars を維持します。
チャネルに環境変数駆動の認証またはセットアップがあり、汎用のシェル環境変数フォールバック、設定/状態チェック、またはセットアッププロンプトがチャネルランタイムを読み込まずに参照できるようにする必要がある場合は、マニフェストの channelEnvVars を使用します。
フックの順序と使い方
モデル/プロバイダー Plugin では、OpenClaw は概ね次の順序でフックを呼び出します。 「使用する場合」列は、素早く判断するためのガイドです。ProviderPlugin.capabilities や suppressBuiltInModel など、OpenClaw が現在は呼び出さない互換性専用のプロバイダーフィールドは、意図的にここには記載していません。
| フック | その役割 | 使用する場面 |
|---|---|---|
catalog | models.json 生成中にプロバイダー設定を models.providers へ公開する | プロバイダーがカタログまたはベース URL のデフォルトを所有する場合 |
applyConfigDefaults | 設定の具体化中に、プロバイダー所有のグローバル設定デフォルトを適用する | デフォルトが認証モード、env、またはプロバイダーモデルファミリーのセマンティクスに依存する場合 |
| (組み込みモデル検索) | OpenClaw はまず通常のレジストリ/カタログパスを試す | (Plugin フックではない) |
normalizeModelId | 検索前にレガシーまたはプレビューのモデル ID エイリアスを正規化する | プロバイダーが正規モデル解決前のエイリアスクリーンアップを所有する場合 |
normalizeTransport | 汎用モデル組み立て前に、プロバイダーファミリーの api / baseUrl を正規化する | プロバイダーが同じトランスポートファミリー内のカスタムプロバイダー ID 向けトランスポートクリーンアップを所有する場合 |
normalizeConfig | ランタイム/プロバイダー解決前に models.providers.<id> を正規化する | プロバイダーに、Plugin と一緒に置くべき設定クリーンアップが必要な場合。バンドルされた Google ファミリーのヘルパーも、サポート対象の Google 設定エントリを補完する |
applyNativeStreamingUsageCompat | 設定プロバイダーにネイティブストリーミング使用量互換の書き換えを適用する | プロバイダーに、エンドポイント駆動のネイティブストリーミング使用量メタデータ修正が必要な場合 |
resolveConfigApiKey | ランタイム認証の読み込み前に、設定プロバイダー向け env マーカー認証を解決する | プロバイダーが独自の env マーカー API キー解決フックを公開する場合 |
resolveSyntheticAuth | 平文を永続化せずに、ローカル/セルフホストまたは設定ベースの認証を表面化する | プロバイダーが合成/ローカル資格情報マーカーで動作できる場合 |
resolveExternalAuthProfiles | プロバイダー所有の外部認証プロファイルを重ねる。CLI/アプリ所有の資格情報では、デフォルトの persistence は runtime-only | プロバイダーが、コピーされたリフレッシュトークンを永続化せずに外部認証資格情報を再利用する場合。マニフェストで contracts.externalAuthProviders を宣言する |
shouldDeferSyntheticProfileAuth | 保存済み合成プロファイルプレースホルダーを env/設定ベース認証の背後に下げる | プロバイダーが、優先順位で勝つべきではない合成プレースホルダープロファイルを保存する場合 |
resolveDynamicModel | ローカルレジストリにまだない、プロバイダー所有モデル ID の同期フォールバック | プロバイダーが任意の上流モデル ID を受け入れる場合 |
prepareDynamicModel | 非同期ウォームアップを行い、その後 resolveDynamicModel が再度実行される | 不明な ID を解決する前に、プロバイダーがネットワークメタデータを必要とする場合 |
normalizeResolvedModel | 埋め込みランナーが解決済みモデルを使用する前の最終書き換え | プロバイダーがトランスポート書き換えを必要とするが、引き続きコアトランスポートを使用する場合 |
normalizeToolSchemas | 埋め込みランナーが参照する前にツールスキーマを正規化する | プロバイダーがトランスポートファミリーのスキーマクリーンアップを必要とする場合 |
inspectToolSchemas | 正規化後に、プロバイダー所有のスキーマ診断を表面化する | コアにプロバイダー固有ルールを教えずに、プロバイダーがキーワード警告を出したい場合 |
resolveReasoningOutputMode | ネイティブまたはタグ付き reasoning-output contract を選択する | ネイティブフィールドではなく、タグ付き reasoning/最終出力がプロバイダーに必要な場合 |
prepareExtraParams | 汎用ストリームオプションラッパー前にリクエストパラメーターを正規化する | プロバイダーがデフォルトのリクエストパラメーターまたはプロバイダーごとのパラメータークリーンアップを必要とする場合 |
createStreamFn | 通常のストリームパスをカスタムトランスポートで完全に置き換える | プロバイダーが単なるラッパーではなく、カスタムのワイヤプロトコルを必要とする場合 |
wrapStreamFn | 汎用ラッパー適用後のストリームラッパー | プロバイダーがカスタムトランスポートなしで、リクエストヘッダー/ボディ/モデル互換ラッパーを必要とする場合 |
resolveTransportTurnState | ネイティブのターンごとのトランスポートヘッダーまたはメタデータを付与する | 汎用トランスポートにプロバイダーネイティブなターン ID を送信させたい場合 |
resolveWebSocketSessionPolicy | ネイティブ WebSocket ヘッダーまたはセッションクールダウンポリシーを付与する | 汎用 WS トランスポートのセッションヘッダーまたはフォールバックポリシーを、プロバイダーが調整したい場合 |
formatApiKey | 認証プロファイルフォーマッター: 保存済みプロファイルがランタイムの apiKey 文字列になる | プロバイダーが追加の認証メタデータを保存し、カスタムランタイムトークン形状を必要とする場合 |
refreshOAuth | カスタムリフレッシュエンドポイントまたはリフレッシュ失敗ポリシー向けの OAuth リフレッシュ上書き | プロバイダーが共有 OpenClaw リフレッシャーに適合しない場合 |
buildAuthDoctorHint | OAuth リフレッシュ失敗時に追加される修復ヒント | リフレッシュ失敗後に、プロバイダー所有の認証修復ガイダンスが必要な場合 |
matchesContextOverflowError | プロバイダー所有のコンテキストウィンドウオーバーフローマッチャー | プロバイダーに、汎用ヒューリスティックでは見逃す生のオーバーフローエラーがある場合 |
classifyFailoverReason | プロバイダー所有のフェイルオーバー理由分類 | プロバイダーが生の API/トランスポートエラーをレート制限/過負荷などに対応付けられる場合 |
isCacheTtlEligible | プロキシ/バックホールプロバイダー向けプロンプトキャッシュポリシー | プロバイダーがプロキシ固有のキャッシュ TTL ゲーティングを必要とする場合 |
buildMissingAuthMessage | 汎用の認証欠落リカバリーメッセージの置き換え | プロバイダー固有の認証欠落リカバリーヒントが必要な場合 |
augmentModelCatalog | 検出後に追加される合成/最終カタログ行 (非推奨。以下を参照) | プロバイダーが models list とピッカーに、合成の前方互換行を必要とする場合 |
resolveThinkingProfile | モデル固有の /think レベルセット、表示ラベル、デフォルト | プロバイダーが、選択されたモデル向けにカスタム思考ラダーまたはバイナリラベルを公開する場合 |
isBinaryThinking | オン/オフ reasoning トグル互換フック | プロバイダーがバイナリの思考オン/オフのみを公開する場合 |
supportsXHighThinking | xhigh reasoning サポート互換フック | プロバイダーがモデルの一部でのみ xhigh を有効にしたい場合 |
resolveDefaultThinkingLevel | デフォルト /think レベル互換フック | プロバイダーがモデルファミリーのデフォルト /think ポリシーを所有する場合 |
isModernModelRef | ライブプロファイルフィルターとスモーク選択向けのモダンモデルマッチャー | プロバイダーがライブ/スモークの優先モデルマッチングを所有する場合 |
prepareRuntimeAuth | 推論直前に、設定済み資格情報を実際のランタイムトークン/キーへ交換する | プロバイダーがトークン交換または短命のリクエスト資格情報を必要とする場合 |
resolveUsageAuth | /usage と関連ステータスサーフェス向けの使用量/課金資格情報を解決する | プロバイダーがカスタム使用量/クォータトークン解析または別の使用量資格情報を必要とする場合 |
fetchUsageSnapshot | 認証解決後に、プロバイダー固有の使用量/クォータスナップショットを取得して正規化する | プロバイダーがプロバイダー固有の使用量エンドポイントまたはペイロードパーサーを必要とする場合 |
createEmbeddingProvider | メモリ/検索用のプロバイダー所有の埋め込みアダプターを構築する | メモリ埋め込みの動作はプロバイダー Plugin に属する |
buildReplayPolicy | プロバイダーのトランスクリプト処理を制御するリプレイポリシーを返す | プロバイダーにはカスタムのトランスクリプトポリシーが必要(たとえば、thinking ブロックの除去) |
sanitizeReplayHistory | 汎用トランスクリプトクリーンアップ後にリプレイ履歴を書き換える | プロバイダーには共有 Compaction ヘルパーを超えるプロバイダー固有のリプレイ書き換えが必要 |
validateReplayTurns | 埋め込みランナーの前に最終的なリプレイターン検証または整形を行う | プロバイダートランスポートには汎用サニタイズ後のより厳格なターン検証が必要 |
onModelSelected | プロバイダー所有の選択後副作用を実行する | モデルがアクティブになったとき、プロバイダーにはテレメトリまたはプロバイダー所有の状態が必要 |
normalizeModelId、normalizeTransport、normalizeConfig はまず一致したプロバイダーPluginを確認し、その後、モデル ID またはトランスポート/設定を実際に変更するものが見つかるまで、フック対応の他のプロバイダーPluginにフォールスルーします。これにより、どのバンドルPluginが書き換えを所有しているかを呼び出し元が知る必要なく、エイリアス/互換プロバイダーのシムを機能させられます。対応している Google ファミリー設定エントリを書き換えるプロバイダーフックがない場合でも、バンドルされた Google 設定ノーマライザーがその互換性クリーンアップを適用します。
プロバイダーが完全にカスタムのワイヤプロトコルやカスタムリクエスト実行機構を必要とする場合、それは別種の拡張です。これらのフックは、OpenClaw の通常の推論ループ上で引き続き動作するプロバイダー挙動のためのものです。
resolveUsageAuth は、OpenClaw が fetchUsageSnapshot を呼び出すべきか、それとも使用量/ステータス表示向けに汎用の資格情報解決へフォールバックすべきかを決定します。プロバイダーに使用量用の資格情報がある場合は { token, accountId? } を返し、プロバイダー所有の使用量認証がリクエストを処理済みで、汎用の API キー/OAuth フォールバックを抑止する必要がある場合は { handled: true } を返し、プロバイダーが使用量認証を処理しなかった場合は null または undefined を返します。
組織または課金用の資格情報は、マニフェストの providerUsageAuthEnvVars で宣言します。これにより、汎用の検出やシークレットスクラブ処理の表示面が、それらを推論認証候補にすることなく認識できます。
プロバイダー例
組み込み例
バンドルされたプロバイダーPluginは、各ベンダーのカタログ、認証、thinking、リプレイ、使用量の要件に合わせて、上記のフックを組み合わせます。信頼できるフックセットはextensions/ 配下の各Pluginにあります。このページは一覧をミラーするのではなく、形を示すものです。
Pass-through catalog providers
Pass-through catalog providers
OpenRouter、Kilocode、Z.AI、xAI は
catalog と resolveDynamicModel / prepareDynamicModel を登録し、OpenClaw の静的カタログに先行して上流のモデル ID を表示できるようにします。OAuth and usage endpoint providers
OAuth and usage endpoint providers
GitHub Copilot、Gemini CLI、ChatGPT Codex、MiniMax、Xiaomi、z.ai は
prepareRuntimeAuth または formatApiKey と resolveUsageAuth + fetchUsageSnapshot を組み合わせ、トークン交換と /usage 連携を所有します。Replay and transcript cleanup families
Replay and transcript cleanup families
共有の名前付きファミリー(
google-gemini、passthrough-gemini、anthropic-by-model、hybrid-anthropic-openai)により、各Pluginがクリーンアップを再実装する代わりに、プロバイダーは buildReplayPolicy を通じてトランスクリプトポリシーへオプトインできます。Catalog-only providers
Catalog-only providers
byteplus、cloudflare-ai-gateway、huggingface、kimi-coding、nvidia、qianfan、synthetic、together、venice、vercel-ai-gateway、volcengine は catalog だけを登録し、共有推論ループ上で動作します。Anthropic-specific stream helpers
Anthropic-specific stream helpers
ベータヘッダー、
/fast / serviceTier、context1m は、汎用 SDK ではなく Anthropic Plugin の公開 api.ts / contract-api.ts 境界(wrapAnthropicProviderStream、resolveAnthropicBetas、resolveAnthropicFastMode、resolveAnthropicServiceTier)内にあります。ランタイムヘルパー
Pluginはapi.runtime を介して選択されたコアヘルパーにアクセスできます。TTS の場合:
textToSpeechは、ファイル/ボイスメモ表示面向けの通常のコア TTS 出力ペイロードを返します。- コアの
messages.tts設定とプロバイダー選択を使用します。 - PCM 音声バッファ + サンプルレートを返します。Pluginはプロバイダー向けにリサンプリング/エンコードする必要があります。
listVoicesはプロバイダーごとに任意です。ベンダー所有の音声ピッカーやセットアップフローで使用します。- 音声一覧には、ロケール、性別、性格タグなど、プロバイダー対応ピッカー向けのより豊富なメタデータを含められます。
- OpenAI と ElevenLabs は現在テレフォニーに対応しています。Microsoft は対応していません。
api.registerSpeechProvider(...) を介して音声プロバイダーを登録することもできます。
- TTS ポリシー、フォールバック、返信配信はコアに保持します。
- ベンダー所有の合成挙動には音声プロバイダーを使用します。
- レガシー Microsoft
edge入力はmicrosoftプロバイダー ID に正規化されます。 - 推奨される所有モデルは企業指向です。OpenClaw がそれらの機能契約を追加するにつれ、1 つのベンダーPluginがテキスト、音声、画像、将来のメディアプロバイダーを所有できます。
- オーケストレーション、フォールバック、設定、チャネル配線はコアに保持します。
- ベンダー挙動はプロバイダーPluginに保持します。
- 追加的な拡張は型付きのままにします。新しい任意メソッド、新しい任意結果フィールド、新しい任意機能を使用します。
- 動画生成もすでに同じパターンに従っています:
- コアが機能契約とランタイムヘルパーを所有する
- ベンダーPluginが
api.registerVideoGenerationProvider(...)を登録する - 機能/チャネルPluginが
api.runtime.videoGeneration.*を使用する
api.runtime.mediaUnderstanding.*は、画像/音声/動画理解向けの推奨共有表示面です。extractStructuredWithModel(...)は、境界付けられたプロバイダー所有の画像優先抽出に対するPlugin向け境界です。少なくとも 1 つの画像入力を含めます。テキスト入力は補足コンテキストです。プロダクトPluginがそれぞれのルートとスキーマを所有し、OpenClaw がプロバイダー/ランタイム境界を所有します。- コアのメディア理解音声設定(
tools.media.audio)とプロバイダーフォールバック順序を使用します。 - 文字起こし出力が生成されない場合(たとえばスキップ/非対応入力)は
{ text: undefined }を返します。 api.runtime.stt.transcribeAudioFile(...)は互換エイリアスとして残ります。
api.runtime.subagent を通じてバックグラウンドのサブエージェント実行を起動することもできます。
providerとmodelは実行ごとの任意オーバーライドであり、永続的なセッション変更ではありません。- OpenClaw は信頼済み呼び出し元に対してのみ、それらのオーバーライドフィールドを尊重します。
- Plugin所有のフォールバック実行については、オペレーターが
plugins.entries.<id>.subagent.allowModelOverride: trueでオプトインする必要があります。 plugins.entries.<id>.subagent.allowedModelsを使用して、信頼済みPluginを特定の正規provider/modelターゲットに制限します。または、任意のターゲットを明示的に許可するには"*"を使用します。- 信頼されていないPluginのサブエージェント実行も動作しますが、オーバーライド要求はサイレントにフォールバックするのではなく拒否されます。
- Pluginが作成したサブエージェントセッションには、作成元Plugin ID がタグ付けされます。フォールバックの
api.runtime.subagent.deleteSession(...)は、それらの所有セッションのみを削除できます。任意のセッション削除には、引き続き管理者スコープの Gateway リクエストが必要です。
api.registerWebSearchProvider(...) を介して Web 検索プロバイダーを登録することもできます。
注:
- プロバイダー選択、資格情報解決、共有リクエストセマンティクスはコアに保持します。
- ベンダー固有の検索トランスポートには Web 検索プロバイダーを使用します。
api.runtime.webSearch.*は、エージェントツールラッパーに依存せずに検索挙動を必要とする機能/チャネルPlugin向けの推奨共有表示面です。
api.runtime.imageGeneration
generate(...): 設定された画像生成プロバイダーチェーンを使用して画像を生成します。listProviders(...): 利用可能な画像生成プロバイダーとその機能を一覧表示します。
Gateway HTTP ルート
Pluginはapi.registerHttpRoute(...) で HTTP エンドポイントを公開できます。
path: Gateway HTTP サーバー配下のルートパス。auth: 必須、"gateway"または"plugin"。通常の Gateway 認証を要求するには"gateway"を使用し、Plugin 管理の認証/Webhook 検証には"plugin"を使用します。match: 任意。"exact"(デフォルト)または"prefix"。handleUpgrade: 同じルート上の WebSocket アップグレードリクエスト用の任意ハンドラー。replaceExisting: 任意。同じ Plugin が自身の既存ルート登録を置き換えることを許可します。handler: ルートがリクエストを処理した場合にtrueを返します。
api.registerHttpHandler(...)は削除され、Plugin 読み込みエラーの原因になります。代わりにapi.registerHttpRoute(...)を使用してください。- Plugin ルートは
authを明示的に宣言する必要があります。 - 完全一致する
path + matchの競合は、replaceExisting: trueでない限り拒否されます。また、ある Plugin が別の Plugin のルートを置き換えることはできません。 - 異なる
authレベルで重複するルートは拒否されます。exact/prefixのフォールスルーチェーンは、同じ認証レベル内のみにしてください。 auth: "plugin"ルートは、オペレーターランタイムスコープを自動的には受け取りません。これは Plugin 管理の Webhook/署名検証用であり、特権的な Gateway ヘルパー呼び出し用ではありません。auth: "gateway"ルートは、Gateway リクエストランタイムスコープ内で実行されます。デフォルトのサーフェス(gatewayRuntimeScopeSurface: "write-default")は意図的に保守的です:- 共有シークレットの bearer 認証(
gateway.auth.mode = "token"/"password")および信頼済みプロキシ以外の認証方式は、呼び出し元がx-openclaw-scopesを送信しても、単一のoperator.writeスコープを取得します - 明示的な
x-openclaw-scopesヘッダーのないtrusted-proxy呼び出し元も、従来のoperator.writeのみのサーフェスを維持します x-openclaw-scopesを送信するtrusted-proxy呼び出し元は、代わりに宣言されたスコープを取得します- ルートは
gatewayRuntimeScopeSurface: "trusted-operator"にオプトインすることで、ID を伴う認証モードでは常にx-openclaw-scopesを尊重できます(ヘッダーがない場合は完全な CLI デフォルトスコープセットにフォールバックします)
- 共有シークレットの bearer 認証(
- 実用上のルール: Gateway 認証の Plugin ルートを暗黙の管理者サーフェスと見なさないでください。ルートに管理者専用の動作が必要な場合は、
trusted-operatorスコープサーフェスにオプトインし、ID を伴う認証モードを要求し、明示的なx-openclaw-scopesヘッダー契約を文書化してください。
Plugin SDK インポートパス
新しい Plugin を作成するときは、モノリシックなopenclaw/plugin-sdk ルート
barrel ではなく、狭い SDK サブパスを使用してください。コアサブパス:
| サブパス | 目的 |
|---|---|
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-outbound,
command-auth, secret-input, webhook-ingress,
channel-targets, channel-actions。承認動作は、無関係な
Plugin フィールドをまたいで混在させるのではなく、1 つの approvalCapability 契約に統合するべきです。チャネル Plugin を参照してください。
ランタイムおよび設定ヘルパーは、対応する焦点を絞った *-runtime サブパス
(approval-runtime, agent-runtime, lazy-runtime, directory-runtime,
text-runtime, runtime-store, system-event-runtime, heartbeat-runtime,
channel-activity-runtime など)配下にあります。広範な config-runtime 互換 barrel ではなく、config-contracts,
plugin-config-runtime, runtime-config-snapshot, config-mutation を優先してください。
openclaw/plugin-sdk/channel-runtime, openclaw/plugin-sdk/channel-lifecycle,
小さなチャネルヘルパー facade、openclaw/plugin-sdk/outbound-runtime,
openclaw/plugin-sdk/outbound-send-deps, 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 は、メッセージ機能を通じてレンダリング可能なものを宣言します:
- セマンティックなプレゼンテーションブロック(
text,context,divider,buttons,select)用のpresentation - ピン留め配信リクエスト用の
delivery-pin
チャネルターゲット解決
チャネル Plugin は、チャネル固有のターゲットセマンティクスを所有するべきです。共有アウトバウンドホストは汎用のままにし、プロバイダールールにはメッセージングアダプターサーフェスを使用してください:messaging.inferTargetChatType({ to })は、ディレクトリ検索の前に、正規化されたターゲットをdirect、group、channelのどれとして扱うべきかを決定します。messaging.targetResolver.looksLikeId(raw, normalized)は、入力がディレクトリ検索ではなく ID らしい解決へ直接進むべきかどうかをコアに伝えます。messaging.targetResolver.reservedLiteralsは、そのプロバイダーのチャネル/セッション参照である裸の単語を列挙します。解決では、予約リテラルを拒否する前に設定済みディレクトリエントリーを保持し、その後ディレクトリミスでは fail closed します。messaging.targetResolver.resolveTarget(...)は、正規化後またはディレクトリミス後に、コアが最終的なプロバイダー所有の解決を必要とする場合の Plugin フォールバックです。messaging.resolveOutboundSessionRoute(...)は、ターゲット解決後のプロバイダー固有セッションルート構築を所有します。
- ピア/グループを検索する前に行うべきカテゴリ判断には
inferTargetChatTypeを使用します。 - 「これを明示的/ネイティブターゲット ID として扱う」チェックには
looksLikeIdを使用します。 - 広範なディレクトリ検索ではなく、プロバイダー固有の正規化フォールバックには
resolveTargetを使用します。 - チャット ID、スレッド ID、JID、ハンドル、ルーム ID などのプロバイダーネイティブ ID は、汎用 SDK フィールドではなく、
target値またはプロバイダー固有 params 内に保持してください。
設定に基づくディレクトリ
設定からディレクトリエントリーを派生する Plugin は、そのロジックを Plugin 内に保持し、openclaw/plugin-sdk/directory-runtime
の共有ヘルパーを再利用するべきです。
チャネルが次のような設定に基づくピア/グループを必要とする場合に使用します:
- allowlist 駆動の DM ピア
- 設定済みチャネル/グループマップ
- アカウントスコープの静的ディレクトリフォールバック
directory-runtime の共有ヘルパーは、汎用操作のみを処理します:
- クエリフィルタリング
- 制限の適用
- 重複排除/正規化ヘルパー
ChannelDirectoryEntry[]の構築
プロバイダーカタログ
プロバイダー Plugin は、registerProvider({ catalog: { run(...) { ... } } }) で推論用のモデルカタログを定義できます。
catalog.run(...) は、OpenClaw が models.providers に書き込むものと同じ形を返します:
- 1 つのプロバイダーエントリー用の
{ provider } - 複数のプロバイダーエントリー用の
{ providers }
catalog を使用します。
catalog.order は、Plugin のカタログが OpenClaw の組み込み暗黙プロバイダーに対していつマージされるかを制御します:
simple: プレーンな API キーまたは env 駆動のプロバイダーprofile: 認証プロファイルが存在すると現れるプロバイダーpaired: 複数の関連プロバイダーエントリーを合成するプロバイダーlate: 他の暗黙プロバイダー後の最後のパス
api.registerModelCatalogProvider({ provider, kinds, staticCatalog, liveCatalog }) を通じて読み取り専用モデル行を公開することもできます。これは list/help/picker サーフェス向けの今後の経路であり、text、voice、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"(および一致する source フィールド)を返せば十分です。 - 資格情報が SecretRef 経由で設定されているものの、現在のコマンド経路で利用できない場合は
configured_unavailableを使用します。
パッケージパック
Plugin ディレクトリには、openclaw.extensions を含む package.json を含めることができます:
<manifestOrPackageName>/<fileBase> になります(manifest id が存在する場合はそれが優先され、そうでなければスコープなしの package.json 名になります)。
Plugin が npm deps を import する場合は、そのディレクトリでインストールして
node_modules を利用できるようにします(npm install / pnpm install)。
セキュリティガードレール: すべての openclaw.extensions エントリは、シンボリックリンク解決後も Plugin
ディレクトリ内に留まる必要があります。パッケージディレクトリの外へ出るエントリは
拒否されます。
セキュリティ上の注意: openclaw plugins install は Plugin 依存関係を
プロジェクトローカルの npm install --omit=dev --ignore-scripts でインストールします(ライフサイクルスクリプトなし、
実行時の dev 依存関係なし)。継承されたグローバル npm install 設定は無視されます。
Plugin の依存関係ツリーは「純粋な JS/TS」に保ち、
postinstall ビルドを必要とするパッケージは避けてください。
任意: openclaw.setupEntry は軽量なセットアップ専用モジュールを指すことができます。
OpenClaw が無効なチャンネル Plugin のセットアップサーフェスを必要とする場合、または
チャンネル Plugin が有効でもまだ未設定の場合、完全な Plugin エントリではなく
setupEntry を読み込みます。これにより、メインの Plugin エントリがツール、フック、その他の実行時専用コードも
結線している場合でも、起動とセットアップを軽量に保てます。
任意: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
は、チャンネルがすでに設定済みの場合でも、Gateway の
listen 前の起動フェーズ中にチャンネル Plugin を同じ setupEntry パスへオプトインできます。
これは、Gateway が listen を開始する前に存在している必要がある起動サーフェスを
setupEntry が完全にカバーしている場合にのみ使用してください。実際には、セットアップエントリが
起動で依存するチャンネル所有のすべての capability を登録する必要があることを意味します。例:
- チャンネル登録自体
- Gateway が listen を開始する前に利用可能である必要がある HTTP ルート
- 同じ期間中に存在している必要がある Gateway メソッド、ツール、またはサービス
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.* に昇格する必要がある場合に、このサーフェスを使用します。
Matrix が現在のバンドル済みの例です。名前付きアカウントがすでに存在する場合は、auth/bootstrap キーのみを
名前付きの昇格済みアカウントへ移動し、常に
accounts.default を作成するのではなく、設定済みの非正規 default-account キーを保持できます。
これらのセットアップパッチアダプターにより、バンドル済みコントラクトサーフェスの検出は遅延されたままになります。import
時は軽量に保たれます。昇格サーフェスは、モジュール import 時にバンドル済みチャンネル起動へ
再突入するのではなく、初回使用時にのみ読み込まれます。
これらの起動サーフェスに Gateway RPC メソッドが含まれる場合は、
Plugin 固有の prefix に置いてください。core 管理者名前空間(config.*,
exec.approvals.*, wizard.*, update.*)は予約済みのままで、Plugin がより狭い scope を要求しても
常に operator.admin に解決されます。
例:
チャンネルカタログメタデータ
チャンネル Plugin はopenclaw.channel を通じてセットアップ/検出メタデータを、
openclaw.install を通じてインストールヒントを公開できます。これにより core カタログはデータを持たずに済みます。
例:
openclaw.channel フィールド:
detailLabel: よりリッチなカタログ/ステータスサーフェス向けの副ラベルdocsLabel: docs リンクのリンクテキストを上書きpreferOver: このカタログエントリが上回るべき、より低優先度の Plugin/チャンネル idselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: 選択サーフェスのコピー制御markdownCapable: 送信フォーマット判断のために、チャンネルを markdown 対応としてマークexposure.configured:falseに設定した場合、設定済みチャンネル一覧サーフェスからチャンネルを非表示exposure.setup:falseに設定した場合、対話型セットアップ/設定ピッカーからチャンネルを非表示exposure.docs: docs ナビゲーションサーフェス向けにチャンネルを internal/private としてマークshowConfigured/showInSetup: 互換性のためにまだ受け入れられるレガシーエイリアス。exposureを優先quickstartAllowFrom: 標準クイックスタートallowFromフローへチャンネルをオプトインforceAccountBinding: アカウントが 1 つしか存在しない場合でも、明示的なアカウント binding を要求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)で
1 つ以上の JSON ファイルを指します(カンマ/セミコロン/PATH 区切り)。各ファイルには
{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] } を含める必要があります。parser は "entries" キーのレガシーエイリアスとして "packages" または "plugins" も受け入れます。
生成されたチャンネルカタログエントリと provider install catalog エントリは、
raw openclaw.install ブロックの横に正規化済み install-source facts を公開します。
正規化済み facts は、npm spec が exact version か floating
selector か、期待される integrity メタデータが存在するか、ローカル
source path も利用可能かを識別します。カタログ/パッケージ identity が判明している場合、
正規化済み facts は、解析された npm package name がその identity からずれていると警告します。
また、defaultChoice が無効な場合、または利用できない source を指す場合、
および有効な npm source なしで npm integrity メタデータが存在する場合にも警告します。
consumer は installSource を加算的な任意フィールドとして扱う必要があります。これにより、
手作業で作られたエントリや catalog shim がそれを合成する必要はありません。
これにより、オンボーディングと診断は Plugin runtime を import せずに
source-plane state を説明できます。
公式の外部 npm エントリでは、exact npmSpec と
expectedIntegrity を優先してください。bare package name と dist-tag は互換性のため引き続き動作しますが、
source-plane warning を表示するため、既存の Plugin を壊さずにカタログを
pinned かつ integrity-checked な install へ移行できます。
オンボーディングがローカルカタログパスからインストールする場合、可能であれば source: "path" と
workspace-relative な sourcePath を持つ managed plugin
plugin index entry を記録します。絶対の operational load path は
plugins.load.paths に残ります。install record は、ローカルワークステーション
path を長寿命の config へ重複して入れることを避けます。これにより、local development install は
source-plane 診断から見えるままにしつつ、2 つ目の raw filesystem-path disclosure
surface を追加しません。永続化された installed_plugin_index SQLite テーブルは install
source of truth であり、Plugin runtime module を読み込まずに refresh できます。
その installRecords map は、Plugin manifest が欠落または無効でも durable です。
その plugins payload は rebuild 可能な manifest view です。
コンテキストエンジン Plugin
コンテキストエンジン Plugin は、ingest、assembly、 compaction のための session context orchestration を所有します。Plugin からapi.registerContextEngine(id, factory) で登録し、active engine を
plugins.slots.contextEngine で選択します。
Plugin が memory search や hook を追加するだけでなく、デフォルトの context
pipeline を置き換える、または拡張する必要がある場合に使用してください。
ctx は、構築時の初期化向けに任意の config、agentDir、workspaceDir
値を公開します。
active harness が persistent backend thread を持つ場合、assemble() は
contextProjection を返すことができます。レガシーな per-turn projection では省略してください。
assembled context を backend thread に一度だけ注入し、epoch が変わるまで再利用する必要がある場合は
{ mode: "thread_bootstrap", epoch } を返します。
engine 所有の compaction pass 後など、engine の semantic context が変化したら
epoch を変更してください。host は thread-bootstrap projection 内で tool-call metadata、input
shape、redacted tool results を保持できるため、新しい
backend thread は raw secret-bearing payload をコピーせずに tool continuity を維持できます。
engine が compaction algorithm を所有していない場合は、compact() を
実装したまま明示的に委譲してください。
新しい capability の追加
Plugin が現在の API に合わない挙動を必要とする場合、private な reach-in で Plugin system を迂回しないでください。不足している capability を追加してください。 推奨される手順:- core contract を定義します。 core が所有すべき shared behavior を決めます: policy、fallback、config merge、lifecycle、channel-facing semantics、 runtime helper shape。
- typed plugin registration/runtime surface を追加します。
OpenClawPluginApiやapi.runtimeを、最小限で有用な typed capability surface で拡張します。 - core + channel/feature consumer を結線します。 チャンネルと feature Plugin は、 vendor 実装を直接 import するのではなく、core 経由で新しい capability を consume するべきです。
- vendor implementation を登録します。 その後、vendor Plugin が capability に対して backend を登録します。
- contract coverage を追加します。 ownership と registration shape が 時間が経っても明示的なままになるよう、テストを追加します。
capability チェックリスト
新しい capability を追加する場合、実装は通常、これらの surface をまとめて触る必要があります。src/<capability>/types.tsのコア契約型src/<capability>/runtime.tsのコアランナー/ランタイムヘルパーsrc/plugins/types.tsの Plugin API 登録サーフェスsrc/plugins/registry.tsの Plugin レジストリ接続- 機能/チャネル Plugin が利用する必要がある場合の
src/plugins/runtime/*における Plugin ランタイム公開 src/test-utils/plugin-registration.tsのキャプチャ/テストヘルパーsrc/plugins/contracts/registry.tsの所有権/契約アサーションdocs/のオペレーター/Plugin ドキュメント
ケイパビリティテンプレート
最小パターン:src/plugins/contracts/registry.ts は
providerContractPluginIds などの所有権ルックアップを公開します。テストでは、
Plugin の contracts.videoGenerationProviders リストが実際に登録する内容と一致することをアサートします):
- コアはケイパビリティ契約 + オーケストレーションを所有する
- ベンダー Plugin はベンダー実装を所有する
- 機能/チャネル Plugin はランタイムヘルパーを利用する
- 契約テストは所有権を明示的に保つ
関連
- Plugin アーキテクチャ — 公開ケイパビリティモデルと形状
- Plugin SDK サブパス
- Plugin SDK セットアップ
- Plugin の構築