プラグイン内部
これは詳細アーキテクチャリファレンスです。実用的なガイドについては、以下を参照してください。
- プラグインをインストールして使う — ユーザーガイド
- はじめに — 最初のプラグインチュートリアル
- チャネルプラグイン — メッセージングチャネルを構築する
- プロバイダープラグイン — モデルプロバイダーを構築する
- SDK概要 — インポートマップと登録API
公開ケイパビリティモデル
ケイパビリティは、OpenClaw内の公開されたネイティブプラグインモデルです。すべての ネイティブOpenClawプラグインは、1つ以上のケイパビリティ種別に対して登録します。| ケイパビリティ | 登録メソッド | プラグイン例 |
|---|---|---|
| テキスト推論 | api.registerProvider(...) | openai, anthropic |
| CLI推論バックエンド | api.registerCliBackend(...) | openai, anthropic |
| 音声 | api.registerSpeechProvider(...) | elevenlabs, microsoft |
| リアルタイム文字起こし | api.registerRealtimeTranscriptionProvider(...) | openai |
| リアルタイム音声 | api.registerRealtimeVoiceProvider(...) | openai |
| メディア理解 | api.registerMediaUnderstandingProvider(...) | openai, google |
| 画像生成 | api.registerImageGenerationProvider(...) | openai, google, fal, minimax |
| 動画生成 | api.registerVideoGenerationProvider(...) | qwen |
| Webフェッチ | api.registerWebFetchProvider(...) | firecrawl |
| Web検索 | api.registerWebSearchProvider(...) | google |
| チャネル / メッセージング | api.registerChannel(...) | msteams, matrix |
外部互換性に関する方針
ケイパビリティモデルはすでにコアに導入されており、現在はバンドル済み / ネイティブプラグインで 使われていますが、外部プラグインの互換性については 「exportされている、したがって固定されている」より厳密な基準が依然として必要です。 現在のガイダンス:- 既存の外部プラグイン: フックベースの統合を動作させ続けること。 これを互換性のベースラインとして扱います
- 新しいバンドル済み / ネイティブプラグイン: ベンダー固有の直接参照や 新しいhook-only設計よりも、明示的なケイパビリティ登録を優先します
- ケイパビリティ登録を採用する外部プラグイン: 許可されますが、 ドキュメントでコントラクトが安定していると明示されない限り、 ケイパビリティ固有のヘルパーサーフェスは進化中のものとして扱ってください
- ケイパビリティ登録APIは意図された方向性です
- レガシーフックは、移行期間中の外部プラグインにとって 破壊的変更を避ける最も安全な経路のままです
- exportされたヘルパーsubpathはすべて同等ではありません。 偶発的なヘルパーexportではなく、狭く文書化された コントラクトを優先してください
プラグインの形状
OpenClawは、読み込まれた各プラグインを、実際の 登録挙動に基づいて形状に分類します(静的メタデータだけではありません)。- plain-capability — ちょうど1つのケイパビリティ種別だけを登録します(たとえば
mistralのようなプロバイダー専用プラグイン) - hybrid-capability — 複数のケイパビリティ種別を登録します(たとえば
openaiはテキスト推論、音声、メディア理解、画像 生成を所有します) - hook-only — フックのみを登録し(型付きまたはカスタム)、 ケイパビリティ、ツール、コマンド、サービスは登録しません
- non-capability — ツール、コマンド、サービス、またはルートを登録しますが、 ケイパビリティは登録しません
openclaw plugins inspect <id>を使用してください。詳細はCLIリファレンスを参照してください。
レガシーフック
before_agent_startフックは、hook-onlyプラグイン向けの
互換性経路として引き続きサポートされています。現実のレガシープラグインは依然としてこれに依存しています。
方向性:
- 動作させ続ける
- レガシーとして文書化する
- モデル / プロバイダーのオーバーライド作業には
before_model_resolveを優先する - プロンプト変更作業には
before_prompt_buildを優先する - 実際の利用が減り、フィクスチャカバレッジが移行の安全性を証明した後にのみ削除する
互換性シグナル
openclaw doctorまたはopenclaw plugins inspect <id>を実行すると、
次のいずれかのラベルが表示されることがあります。
| シグナル | 意味 |
|---|---|
| config valid | 設定は正常に解析され、プラグインも解決される |
| compatibility advisory | プラグインがサポートされているが古いパターンを使っている(例: hook-only) |
| legacy warning | プラグインが非推奨のbefore_agent_startを使っている |
| hard error | 設定が無効、またはプラグインの読み込みに失敗した |
hook-onlyもbefore_agent_startも、現時点ではプラグインを壊しません —
hook-onlyは助言的なものに過ぎず、before_agent_startも警告を出すだけです。これらの
シグナルはopenclaw status --allおよびopenclaw plugins doctorにも表示されます。
アーキテクチャ概要
OpenClawのプラグインシステムは4つのレイヤーを持ちます。- マニフェスト + 検出
OpenClawは、設定されたパス、ワークスペースルート、
グローバル拡張ルート、およびバンドル済み拡張から候補プラグインを見つけます。
検出では、まずネイティブ
openclaw.plugin.jsonマニフェストと、サポートされたバンドルマニフェストを読み込みます。 - 有効化 + 検証 コアは、検出されたプラグインが有効、無効、ブロック済み、 またはメモリーのような排他的スロットに選択されたものかを決定します。
- ランタイム読み込み ネイティブOpenClawプラグインは、jitiを介してプロセス内で読み込まれ、 中央レジストリにケイパビリティを登録します。互換性のあるバンドルは、 ランタイムコードをimportせずにレジストリレコードへ正規化されます。
- サーフェス消費 OpenClawの他の部分はレジストリを読んで、ツール、チャネル、プロバイダー セットアップ、フック、HTTPルート、CLIコマンド、およびサービスを公開します。
- parse時メタデータは
registerCli(..., { descriptors: [...] })から取得されます - 実際のプラグインCLIモジュールは遅延のままにでき、最初の呼び出し時に登録できます
- 検出 + config検証は、プラグインコードを実行せずに manifest/schemaメタデータから機能するべきです
- ネイティブのランタイム挙動は、プラグインモジュールの
register(api)経路から来ます
チャネルプラグインと共有messageツール
チャネルプラグインは、通常のチャット操作のために、 個別の送信 / 編集 / リアクションツールを別途登録する必要はありません。OpenClawはコアに 1つの共有messageツールを保持し、その背後にあるチャネル固有の検出と実行は
チャネルプラグインが所有します。
現在の境界は次のとおりです。
- コアは共有
messageツールホスト、プロンプト配線、セッション / スレッド の記録、および実行ディスパッチを所有します - チャネルプラグインはスコープ付きアクション検出、ケイパビリティ検出、および 任意のチャネル固有schemaフラグメントを所有します
- チャネルプラグインは、スレッドIDを会話IDがどのようにエンコードするか、 または親会話から継承するかといった、 プロバイダー固有のセッション会話文法を所有します
- チャネルプラグインは、そのアクションアダプターを通じて最終アクションを実行します
ChannelMessageActionAdapter.describeMessageTool(...)です。この統合された検出呼び出しにより、
プラグインは表示されるアクション、ケイパビリティ、およびschemaへの寄与をまとめて返せるため、
これらの要素がずれません。
コアは、その検出ステップにランタイムスコープを渡します。重要なフィールドは次のとおりです。
accountIdcurrentChannelIdcurrentThreadTscurrentMessageIdsessionKeysessionIdagentId- 信頼された受信
requesterSenderId
messageツールにチャネル固有の分岐をハードコードする必要はありません。
これが、埋め込みランナーのルーティング変更が依然としてプラグイン作業である理由です。ランナーは、
共有messageツールが
現在のターンに対して正しいチャネル所有サーフェスを公開できるよう、
現在のチャット / セッションIDをプラグイン検出境界へ転送する責任を持ちます。
チャネル所有の実行ヘルパーについては、バンドル済みプラグインは実行
ランタイムを自分自身の拡張モジュール内に保持するべきです。コアはもはや、
src/agents/tools配下でDiscord、
Slack、Telegram、WhatsAppのmessage-actionランタイムを所有しません。
個別のplugin-sdk/*-action-runtime subpathは公開しておらず、バンドル済み
プラグインは、自身の拡張所有モジュールから
ローカルランタイムコードを直接importするべきです。
同じ境界は、一般にプロバイダー名付きSDKシームにも当てはまります。コアは
Slack、Discord、Signal、
WhatsApp、または類似の拡張向けのチャネル固有コンビニエンスbarrelをimportすべきではありません。
コアがある挙動を必要とする場合は、バンドル済みプラグイン自身の
api.ts / runtime-api.ts barrelを使うか、
必要性を共有SDK内の狭い汎用ケイパビリティへ昇格させてください。
特にpollについては、2つの実行経路があります。
outbound.sendPollは、共通の pollモデルに適合するチャネル向けの共有ベースラインですactions.handleAction("poll")は、チャネル固有の pollセマンティクスまたは追加のpollパラメーター向けの推奨経路です
ケイパビリティ所有権モデル
OpenClawは、ネイティブプラグインを、無関係な統合の寄せ集めではなく、 企業または機能の所有権境界として扱います。 これは次を意味します。- 企業プラグインは、通常、その企業のOpenClaw向け サーフェスをすべて所有するべきです
- 機能プラグインは、通常、導入する機能サーフェス全体を所有するべきです
- チャネルは、プロバイダー挙動をアドホックに再実装するのではなく、 共有コアケイパビリティを消費するべきです
- バンドル済み
openaiプラグインは、OpenAIのモデルプロバイダー挙動と、OpenAIの 音声 + リアルタイム音声 + メディア理解 + 画像生成の挙動を所有します - バンドル済み
elevenlabsプラグインは、ElevenLabsの音声挙動を所有します - バンドル済み
microsoftプラグインは、Microsoftの音声挙動を所有します - バンドル済み
googleプラグインは、Googleのモデルプロバイダー挙動に加えて、Googleの メディア理解 + 画像生成 + Web検索の挙動を所有します - バンドル済み
firecrawlプラグインは、FirecrawlのWebフェッチ挙動を所有します - バンドル済み
minimax、mistral、moonshot、zaiプラグインは、 それぞれのメディア理解バックエンドを所有します voice-callプラグインは機能プラグインです。通話トランスポート、ツール、 CLI、ルート、およびTwilioメディアストリームのブリッジを所有しますが、 ベンダープラグインを直接importするのではなく、 共有音声 + リアルタイム文字起こし + リアルタイム音声ケイパビリティを消費します
- OpenAIは、テキストモデル、音声、画像、そして 将来の動画にまたがっても1つのプラグイン内に存在します
- 他のベンダーも、自身のサーフェス領域について同じことができます
- チャネルは、どのベンダープラグインがそのプロバイダーを所有しているかを気にしません。 コアが公開する共有ケイパビリティコントラクトを消費します
- plugin = 所有権境界
- capability = 複数のプラグインが実装または消費できるコアコントラクト
- コアで不足しているケイパビリティを定義する
- それをプラグインAPI / ランタイムを通じて型付きで公開する
- チャネル / 機能をそのケイパビリティに対して配線する
- ベンダープラグインに実装を登録させる
ケイパビリティのレイヤリング
コードをどこに置くべきかを判断する際は、次のメンタルモデルを使ってください。- コアケイパビリティレイヤー: 共有オーケストレーション、ポリシー、フォールバック、config マージルール、配信セマンティクス、および型付きコントラクト
- ベンダープラグインレイヤー: ベンダー固有API、認証、モデルカタログ、音声 合成、画像生成、将来の動画バックエンド、利用量エンドポイント
- チャネル / 機能プラグインレイヤー: Slack / Discord / voice-callなどの統合。 コアケイパビリティを消費し、サーフェス上に提示します
- コアは返信時TTSポリシー、フォールバック順序、設定、チャネル配信を所有します
openai、elevenlabs、microsoftは合成実装を所有しますvoice-callは電話向けTTSランタイムヘルパーを消費します
複数ケイパビリティを持つ企業プラグインの例
企業プラグインは、外から見て一貫性があるように感じられるべきです。OpenClawに、 モデル、音声、リアルタイム文字起こし、リアルタイム音声、メディア 理解、画像生成、動画生成、Webフェッチ、およびWeb検索に関する共有 コントラクトがあるなら、ベンダーはそのすべてのサーフェスを1か所で所有できます。- 1つのプラグインがベンダーサーフェスを所有する
- コアは依然としてケイパビリティコントラクトを所有する
- チャネルと機能プラグインは、ベンダーコードではなく
api.runtime.*ヘルパーを消費する - コントラクトテストは、プラグインが所有すると主張するケイパビリティを 実際に登録したことを検証できる
ケイパビリティ例: 動画理解
OpenClawはすでに、画像 / 音声 / 動画理解を1つの共有 ケイパビリティとして扱っています。同じ所有権モデルがここにも当てはまります。- コアがmedia-understandingコントラクトを定義する
- ベンダープラグインが、該当するものとして
describeImage、transcribeAudio、describeVideoを登録する - チャネルと機能プラグインは、ベンダーコードに直接配線するのではなく、 共有コア挙動を消費する
api.registerVideoGenerationProvider(...)実装をそれに対して登録します。
具体的なロールアウトチェックリストが必要ですか。以下を参照してください。
Capability Cookbook。
コントラクトと強制
プラグインAPIサーフェスは、意図的に型付けされ、OpenClawPluginApiに集約されています。このコントラクトは、
サポートされる登録ポイントと、プラグインが依存できる
ランタイムヘルパーを定義します。
これが重要な理由:
- プラグイン作者は、1つの安定した内部標準を得られる
- コアは、2つのプラグインが同じ provider idを登録するような重複所有を拒否できる
- 起動時に、不正な登録に対する実用的な診断を提示できる
- コントラクトテストは、バンドル済みプラグインの所有権を強制し、 静かなドリフトを防げる
- ランタイム登録の強制 プラグインレジストリは、プラグイン読み込み時に登録を検証します。例: 重複するprovider id、重複するspeech provider id、および不正な 登録は、未定義動作ではなくプラグイン診断を生成します。
- コントラクトテスト バンドル済みプラグインは、テスト実行中にコントラクトレジストリへ捕捉されるため、 OpenClawは所有権を明示的に検証できます。現在、これはモデル プロバイダー、音声プロバイダー、Web検索プロバイダー、およびバンドル済み登録 所有権に使われています。
コントラクトに含めるべきもの
良いプラグインコントラクトは次のとおりです。- 型付き
- 小さい
- ケイパビリティ固有
- コアが所有
- 複数のプラグインで再利用可能
- ベンダー知識なしにチャネル / 機能が消費可能
- コアに隠されたベンダー固有ポリシー
- レジストリを迂回する一回限りのプラグイン用エスケープハッチ
- ベンダー実装へ直接到達するチャネルコード
OpenClawPluginApiまたはapi.runtimeの一部ではないアドホックなランタイムオブジェクト
実行モデル
ネイティブOpenClawプラグインは、Gatewayと同一プロセス内で動作します。 サンドボックス化はされていません。読み込まれたネイティブプラグインは、 コアコードと同じプロセスレベルの信頼境界を持ちます。 影響:- ネイティブプラグインは、ツール、ネットワークハンドラー、フック、サービスを登録できます
- ネイティブプラグインのバグはgatewayをクラッシュさせたり不安定化させたりできます
- 悪意あるネイティブプラグインは、OpenClawプロセス内での任意コード実行と同等です
@openclaw/<id>、または
意図的により狭いプラグインの役割を公開する場合は、
-provider、-plugin、-speech、-sandbox、-media-understandingのような
承認された型付きサフィックスを使います。
重要な信頼上の注意:
plugins.allowはplugin idを信頼し、ソースの来歴は信頼しません。- バンドル済みプラグインと同じidを持つワークスペースプラグインは、 そのワークスペースプラグインが有効化 / allowlist入りされている場合、 意図的にバンドル済みコピーをシャドウします。
- これは正常であり、ローカル開発、パッチテスト、ホットフィックスに役立ちます。
export境界
OpenClawは、実装上の便宜ではなくケイパビリティをexportします。 ケイパビリティ登録は公開のままにしつつ、非コントラクトのヘルパーexportは削減してください。- バンドル済みプラグイン固有のhelper subpath
- 公開APIとして意図されていないランタイム配管subpath
- ベンダー固有のコンビニエンスヘルパー
- 実装詳細であるsetup / オンボーディングヘルパー
plugin-sdk/feishu、plugin-sdk/feishu-setup、plugin-sdk/zalo、
plugin-sdk/zalo-setup、およびいくつかのplugin-sdk/matrix*シームがあります。これらは
新しいサードパーティプラグイン向けの推奨SDKパターンではなく、
予約済みの実装詳細exportとして扱ってください。
読み込みパイプライン
起動時に、OpenClawは概ね次の処理を行います。- 候補プラグインルートを検出する
- ネイティブまたは互換バンドルのマニフェストとパッケージメタデータを読み込む
- 安全でない候補を拒否する
- プラグイン設定を正規化する(
plugins.enabled、allow、deny、entries、slots、load.paths) - 各候補の有効化可否を決定する
- 有効なネイティブモジュールをjiti経由で読み込む
- ネイティブの
register(api)(またはactivate(api)— レガシーエイリアス)フックを呼び出し、登録をプラグインレジストリへ収集する - レジストリをコマンド / ランタイムサーフェスに公開する
activateはregisterのレガシーエイリアスです — ローダーは存在する方(def.register ?? def.activate)を解決し、同じ地点で呼び出します。すべてのバンドル済みプラグインはregisterを使用しています。新しいプラグインではregisterを優先してください。Manifest-firstの挙動
manifestはコントロールプレーンの真実の源です。OpenClawはこれを使って次を行います。- プラグインを識別する
- 宣言されたチャネル / Skills / config schemaまたはバンドル機能を検出する
plugins.entries.<id>.configを検証する- Control UIのラベル / プレースホルダーを拡張する
- インストール / カタログメタデータを表示する
ローダーがキャッシュするもの
OpenClawは、短期間のプロセス内キャッシュを次のために保持します。- 検出結果
- manifestレジストリデータ
- 読み込み済みプラグインレジストリ
- これらのキャッシュを無効にするには、
OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1またはOPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1を設定してください。 - キャッシュ期間は
OPENCLAW_PLUGIN_DISCOVERY_CACHE_MSとOPENCLAW_PLUGIN_MANIFEST_CACHE_MSで調整できます。
レジストリモデル
読み込まれたプラグインは、ランダムなコアグローバルを直接変更しません。中央の プラグインレジストリに登録します。 レジストリは次を追跡します。- プラグインレコード(識別情報、ソース、出所、状態、診断)
- ツール
- レガシーフックと型付きフック
- チャネル
- プロバイダー
- Gateway RPCハンドラー
- HTTPルート
- CLI登録子
- バックグラウンドサービス
- プラグイン所有コマンド
- プラグインモジュール -> レジストリ登録
- コアランタイム -> レジストリ消費
会話バインディングコールバック
会話をバインドするプラグインは、承認が解決されたときに反応できます。 バインド要求が承認または拒否された後にコールバックを受け取るには、api.onConversationBindingResolved(...)を使用してください。
status:"approved"または"denied"decision:"allow-once"、"allow-always"、または"deny"binding: 承認済みリクエストの解決済みバインディングrequest: 元のリクエスト概要、デタッチヒント、sender id、および 会話メタデータ
プロバイダーのランタイムフック
プロバイダープラグインは現在、2つのレイヤーを持ちます。- manifestメタデータ: ランタイム読み込み前の
安価なenv認証参照用の
providerAuthEnvVars、およびランタイム読み込み前の 安価なオンボーディング / auth-choice ラベルやCLIフラグメタデータ用のproviderAuthChoices - config時フック:
catalog/ レガシーdiscoveryおよびapplyConfigDefaults - ランタイムフック:
normalizeModelId,normalizeTransport,normalizeConfig,applyNativeStreamingUsageCompat,resolveConfigApiKey,resolveSyntheticAuth,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を使用してください。
オンボーディング / auth-choice CLI
サーフェスが、プロバイダーランタイムを読み込まずにそのプロバイダーのchoice id、
group label、および単純な
単一フラグ認証配線を認識する必要がある場合は、manifestのproviderAuthChoicesを使ってください。プロバイダーランタイムの
envVarsは、オンボーディングラベルやOAuth
client-id / client-secret設定変数のような、
運用者向けヒントとして保持してください。
フック順序と使い方
モデル / プロバイダープラグインについて、OpenClawは概ね次の順序でフックを呼び出します。 「When to use」列は、素早い判断ガイドです。| # | フック | 役割 | 使うべき場面 |
|---|---|---|---|
| 1 | catalog | models.json生成時に、プロバイダー設定をmodels.providersへ公開する | プロバイダーがカタログまたはbase URLデフォルトを所有している |
| 2 | applyConfigDefaults | config具体化時に、プロバイダー所有のグローバルconfigデフォルトを適用する | デフォルトがauthモード、env、またはプロバイダーのモデルファミリー意味論に依存する |
| — | (built-in model lookup) | OpenClawはまず通常のレジストリ / カタログ経路を試す | (プラグインフックではない) |
| 3 | normalizeModelId | lookup前に、レガシーまたはプレビューのmodel-idエイリアスを正規化する | 正規のモデル解決前に、プロバイダーがエイリアスクリーンアップを所有している |
| 4 | normalizeTransport | 汎用モデル構築前に、プロバイダーファミリーのapi / baseUrlを正規化する | 同じトランスポートファミリー内のカスタムprovider id向けトランスポートクリーンアップをプロバイダーが所有している |
| 5 | normalizeConfig | ランタイム / プロバイダー解決前にmodels.providers.<id>を正規化する | プロバイダーが、プラグイン内にあるべきconfigクリーンアップを必要としている。バンドル済みGoogleファミリーヘルパーは、サポートされるGoogle configエントリーも後方保護する |
| 6 | applyNativeStreamingUsageCompat | config providersに対して、ネイティブstreaming-usage互換リライトを適用する | エンドポイント駆動のネイティブstreaming usageメタデータ修正が必要 |
| 7 | resolveConfigApiKey | ランタイムauth読み込み前に、config providers向けのenv-marker認証を解決する | プロバイダー所有のenv-marker APIキー解決がある。amazon-bedrockにもここにbuilt-inのAWS env-marker resolverがある |
| 8 | resolveSyntheticAuth | 平文を永続化せずに、local / self-hostedまたはconfig-backed認証を表面化する | プロバイダーがsynthetic / local credential markerで動作できる |
| 9 | shouldDeferSyntheticProfileAuth | 保存されたsynthetic profile placeholderを、env / config-backed authより低優先にする | プロバイダーが優先されるべきでないsynthetic placeholder profileを保存している |
| 10 | resolveDynamicModel | ローカルレジストリにまだないプロバイダー所有model id向けの同期フォールバック | プロバイダーが任意のupstream model idを受け付ける |
| 11 | prepareDynamicModel | 非同期ウォームアップ後に、resolveDynamicModelを再実行する | 不明なidを解決する前にネットワークメタデータが必要 |
| 12 | normalizeResolvedModel | 埋め込みランナーが解決済みモデルを使う前の最終リライト | プロバイダーがトランスポートリライトを必要とするが、依然としてコアトランスポートを使う |
| 13 | contributeResolvedModelCompat | 別の互換トランスポートの背後にあるベンダーモデル向けのcompatフラグを提供する | プロバイダーを乗っ取らずに、プロキシトランスポート上で自分のモデルを認識する |
| 14 | capabilities | 共有コアロジックで使われる、プロバイダー所有のトランスクリプト / ツールメタデータ | プロバイダーがtranscript / provider-familyの癖を必要とする |
| 15 | normalizeToolSchemas | 埋め込みランナーが見る前にtool schemaを正規化する | プロバイダーがtransport-family schemaクリーンアップを必要とする |
| 16 | inspectToolSchemas | 正規化後に、プロバイダー所有のschema診断を表面化する | コアにプロバイダー固有ルールを教えずに、プロバイダーがキーワード警告を出したい |
| 17 | resolveReasoningOutputMode | ネイティブまたはtaggedなreasoning-output contractを選択する | プロバイダーがネイティブフィールドの代わりに、tagged reasoning / final outputを必要とする |
| 18 | prepareExtraParams | 汎用stream option wrapper前のリクエストパラメーター正規化 | デフォルトリクエストパラメーターまたはプロバイダーごとのパラメータークリーンアップが必要 |
| 19 | createStreamFn | 通常のstream path全体をカスタムトランスポートに置き換える | ラッパーではなく、カスタムwire protocolが必要 |
| 20 | wrapStreamFn | 汎用ラッパー適用後のstreamラッパー | カスタムトランスポートではなく、リクエストヘッダー / body / model互換ラッパーが必要 |
| 21 | resolveTransportTurnState | ネイティブのターン単位トランスポートヘッダーまたはメタデータを付加する | 汎用トランスポートで、プロバイダーネイティブのターンIDを送信したい |
| 22 | resolveWebSocketSessionPolicy | ネイティブWebSocketヘッダーまたはセッションクールダウンポリシーを付加する | 汎用WSトランスポートで、セッションヘッダーやフォールバックポリシーを調整したい |
| 23 | formatApiKey | auth-profile formatter: 保存済みprofileをランタイムapiKey文字列にする | プロバイダーが追加のauthメタデータを保存し、カスタムのランタイムトークン形状を必要とする |
| 24 | refreshOAuth | カスタムrefresh endpointまたはrefresh失敗ポリシー向けのOAuth refreshオーバーライド | 共有pi-ai refresherに適合しない |
| 25 | buildAuthDoctorHint | OAuth refresh失敗時に付加される修復ヒント | プロバイダー所有のauth修復ガイダンスが必要 |
| 26 | matchesContextOverflowError | プロバイダー所有のコンテキストウィンドウあふれマッチャー | 汎用ヒューリスティックでは見落とす生のoverflow errorがある |
| 27 | classifyFailoverReason | プロバイダー所有のフェイルオーバー理由分類 | 生のAPI / transport errorを、rate-limit / overloadなどにマップできる |
| 28 | isCacheTtlEligible | proxy / backhaul provider向けのプロンプトキャッシュポリシー | proxy固有のcache TTLゲーティングが必要 |
| 29 | buildMissingAuthMessage | 汎用missing-auth復旧メッセージの置き換え | プロバイダー固有のmissing-auth復旧ヒントが必要 |
| 30 | suppressBuiltInModel | 古いupstream modelの抑制と、任意のユーザー向けエラーヒント | 古いupstream行を隠したり、ベンダーヒントに置き換えたい |
| 31 | augmentModelCatalog | 検出後に、synthetic / 最終catalog行を追記する | models listやpickerにsyntheticなforward-compat行が必要 |
| 32 | isBinaryThinking | binary-thinking provider向けのオン / オフ推論トグル | プロバイダーがbinary thinkingのオン / オフのみを公開する |
| 33 | supportsXHighThinking | 選択されたモデル向けのxhigh推論サポート | プロバイダーが一部のモデルだけでxhighを有効にしたい |
| 34 | resolveDefaultThinkingLevel | 特定モデルファミリー向けのデフォルト/thinkレベル | そのモデルファミリー向けのデフォルト/thinkポリシーをプロバイダーが所有している |
| 35 | isModernModelRef | live profile filterおよびsmoke選択向けのmodern-model matcher | live / smoke優先モデルマッチングをプロバイダーが所有している |
| 36 | prepareRuntimeAuth | 推論直前に、設定済み認証情報を実際のランタイムトークン / キーへ交換する | トークン交換または短命リクエスト認証情報が必要 |
| 37 | resolveUsageAuth | /usageおよび関連statusサーフェス向けの利用量 / 課金認証を解決する | カスタムのusage / quotaトークン解析、または異なるusage認証情報が必要 |
| 38 | fetchUsageSnapshot | auth解決後に、プロバイダー固有のusage / quotaスナップショットを取得して正規化する | プロバイダー固有のusage endpointまたはpayload parserが必要 |
| 39 | createEmbeddingProvider | メモリー / 検索向けの、プロバイダー所有embedding adapterを構築する | メモリーembedding挙動はプロバイダープラグインに属する |
| 40 | buildReplayPolicy | プロバイダー向けのtranscript処理を制御するreplay policyを返す | カスタムtranscript policy(たとえばthinking block除去)が必要 |
| 41 | sanitizeReplayHistory | 汎用transcriptクリーンアップ後にreplay historyを書き換える | 共有compaction helperを超える、プロバイダー固有replay書き換えが必要 |
| 42 | validateReplayTurns | 埋め込みランナー前の最終replay turn検証または整形 | 汎用sanitation後でも、provider transportがより厳密なturn検証を必要とする |
| 43 | onModelSelected | プロバイダー所有の選択後副作用を実行する | モデルが有効になったときのtelemetryやプロバイダー所有stateが必要 |
normalizeModelId、normalizeTransport、normalizeConfigはまず
一致したprovider pluginを確認し、その後、実際にmodel idまたは
transport / configを変更するものが現れるまで、他のフック対応provider pluginへフォールスルーします。これにより、
callerがどのバンドル済みプラグインがそのリライトを所有しているかを知る必要なく、
alias / compat provider shimが動作し続けます。いずれのprovider hookも
サポートされたGoogleファミリーconfigエントリーを書き換えない場合、
バンドル済みGoogle config normalizerがその互換性クリーンアップを引き続き適用します。
プロバイダーが完全なカスタムwire protocolまたはカスタムリクエスト実行器を必要とする場合、
それは別種の拡張です。これらのフックは、
OpenClawの通常の推論ループ上で動作するプロバイダー挙動向けです。
プロバイダー例
組み込み例
- Anthropicは
resolveDynamicModel、capabilities、buildAuthDoctorHint、resolveUsageAuth、fetchUsageSnapshot、isCacheTtlEligible、resolveDefaultThinkingLevel、applyConfigDefaults、isModernModelRef、 およびwrapStreamFnを使います。これはClaude 4.6のforward-compat、 provider-familyヒント、auth修復ガイダンス、usage endpoint統合、 prompt-cache適格性、auth対応configデフォルト、Claudeの default / adaptive thinkingポリシー、およびbeta header、/fast/serviceTier、context1m向けのAnthropic固有stream shapingを所有するためです。 - AnthropicのClaude固有stream helperは、現時点では
バンドル済みプラグイン自身の公開
api.ts/contract-api.tsシーム内に留まっています。そのパッケージサーフェスはwrapAnthropicProviderStream、resolveAnthropicBetas、resolveAnthropicFastMode、resolveAnthropicServiceTier、およびより低レベルの Anthropic wrapper builderをexportしており、1つのプロバイダーのbeta-headerルールのために 汎用SDKを広げていません。 - OpenAIは
resolveDynamicModel、normalizeResolvedModel、capabilitiesに加えて、buildMissingAuthMessage、suppressBuiltInModel、augmentModelCatalog、supportsXHighThinking、isModernModelRefを使います。 これはGPT-5.4のforward-compat、直接のOpenAIopenai-completions->openai-responses正規化、Codex対応auth ヒント、Spark抑制、syntheticなOpenAI list行、およびGPT-5のthinking / live-modelポリシーを所有するためです。openai-responses-defaultsstream familyは、 attribution header、/fast/serviceTier、text verbosity、ネイティブCodex Web検索、 reasoning-compat payload shaping、およびResponses context管理向けの 共有ネイティブOpenAI Responses wrapperを所有します。 - OpenRouterは
catalogに加えてresolveDynamicModelとprepareDynamicModelを使います。これはプロバイダーがパススルーであり、 OpenClawの静的カタログが更新される前に新しい model idを公開しうるためです。また、 provider固有リクエストヘッダー、ルーティングメタデータ、reasoningパッチ、および prompt-cacheポリシーをコアの外に保つために、capabilities、wrapStreamFn、isCacheTtlEligibleも使います。そのreplay policyはpassthrough-geminifamilyから来ており、openrouter-thinkingstream familyは proxy reasoning注入と未対応モデル /autoスキップを所有します。 - GitHub Copilotは
catalog、auth、resolveDynamicModel、capabilitiesに加えてprepareRuntimeAuthとfetchUsageSnapshotを使います。 これは、プロバイダー所有のdevice login、モデルフォールバック挙動、Claudeのtranscriptの癖、 GitHub token -> Copilot token交換、およびプロバイダー所有のusage endpointが必要なためです。 - OpenAI Codexは
catalog、resolveDynamicModel、normalizeResolvedModel、refreshOAuth、augmentModelCatalogに加えてprepareExtraParams、resolveUsageAuth、fetchUsageSnapshotを使います。 これは依然としてコアOpenAIトランスポート上で動作しつつ、 そのトランスポート / base URL正規化、OAuth refreshフォールバックポリシー、 デフォルトトランスポート選択、syntheticなCodexカタログ行、およびChatGPT usage endpoint統合を所有するためです。 direct OpenAIと同じopenai-responses-defaultsstream familyを共有します。 - Google AI StudioとGemini CLI OAuthは
resolveDynamicModel、buildReplayPolicy、sanitizeReplayHistory、resolveReasoningOutputMode、wrapStreamFn、isModernModelRefを使います。これはgoogle-geminireplay familyがGemini 3.1のforward-compatフォールバック、 ネイティブGemini replay検証、bootstrap replay sanitization、tagged reasoning-output mode、およびmodern-model matchingを所有し、google-thinkingstream familyがGemini thinking payload正規化を所有するためです。 Gemini CLI OAuthはさらに、トークン整形、トークン解析、およびquota endpoint 配線のためにformatApiKey、resolveUsageAuth、fetchUsageSnapshotも使います。 - Anthropic Vertexは、
anthropic-by-modelreplay familyを通じてbuildReplayPolicyを使います。これにより、 Claude固有replayクリーンアップが、すべてのanthropic-messagestransportではなく、 Claude idに限定されます。 - Amazon Bedrockは
buildReplayPolicy、matchesContextOverflowError、classifyFailoverReason、resolveDefaultThinkingLevelを使います。これは Anthropic-on-Bedrockトラフィック向けのBedrock固有 throttle / not-ready / context-overflowエラー分類を所有するためです。 そのreplay policyは、依然として同じ Claude専用anthropic-by-modelガードを共有します。 - OpenRouter、Kilocode、Opencode、Opencode Goは
buildReplayPolicyをpassthrough-geminireplay family経由で使います。これは OpenAI互換トランスポートを通じてGeminiモデルをプロキシし、 ネイティブGemini replay検証や bootstrapリライトなしにGemini thought-signature sanitizationを必要とするためです。 - MiniMaxは、
hybrid-anthropic-openaireplay family経由でbuildReplayPolicyを使います。これは 1つのプロバイダーがAnthropic-messageとOpenAI互換セマンティクスの両方を所有するためです。 Anthropic側ではClaude専用thinking-block除去を維持しつつ、 reasoning output modeをネイティブへ上書きし、minimax-fast-modestream familyが共有stream path上の fast-mode modelリライトを所有します。 - Moonshotは
catalogに加えてwrapStreamFnを使います。これは依然として共有 OpenAI transportを使いながら、プロバイダー所有のthinking payload正規化を必要とするためです。moonshot-thinkingstream familyは、configと/think状態を ネイティブbinary thinking payloadへマッピングします。 - Kilocodeは
catalog、capabilities、wrapStreamFn、isCacheTtlEligibleを使います。これはプロバイダー所有のrequest header、 reasoning payload正規化、Gemini transcriptヒント、およびAnthropic cache-TTLゲーティングを必要とするためです。kilocode-thinkingstream familyは、kilo/autoやその他の 明示的reasoning payloadをサポートしないproxy model idをスキップしつつ、 共有proxy stream path上でKilo thinking注入を保持します。 - Z.AIは
resolveDynamicModel、prepareExtraParams、wrapStreamFn、isCacheTtlEligible、isBinaryThinking、isModernModelRef、resolveUsageAuth、fetchUsageSnapshotを使います。これはGLM-5フォールバック、tool_streamデフォルト、binary thinking UX、modern-model matching、および usage auth + quota取得の両方を所有するためです。tool-stream-default-onstream familyは、 デフォルトオンのtool_streamwrapperをプロバイダーごとの手書き glueの外へ保ちます。 - xAIは
normalizeResolvedModel、normalizeTransport、contributeResolvedModelCompat、prepareExtraParams、wrapStreamFn、resolveSyntheticAuth、resolveDynamicModel、isModernModelRefを使います。 これはネイティブxAI Responses transport正規化、Grok fast-mode aliasリライト、デフォルトtool_stream、strict-tool / reasoning-payload クリーンアップ、plugin所有ツール向けのフォールバックauth再利用、 forward-compatなGrokモデル解決、およびxAI tool-schema profile、未対応schema keyword、ネイティブweb_search、HTML entity tool-call引数デコードのような、プロバイダー所有compat patchを所有するためです。 - Mistral、OpenCode Zen、OpenCode Goは、transcript / toolingの癖を
コアの外に保つために
capabilitiesのみを使います。 byteplus、cloudflare-ai-gateway、huggingface、kimi-coding、nvidia、qianfan、synthetic、together、venice、vercel-ai-gateway、volcengineのような カタログ専用バンドル済みプロバイダーは、catalogのみを使います。- Qwenは、テキストプロバイダー向けの
catalogに加えて、 そのマルチモーダルサーフェス向けに共有media-understandingと video-generation登録を使います。 - MiniMaxとXiaomiは、推論自体は共有トランスポートを通って動作するものの、
その
/usage挙動がプラグイン所有であるため、catalogに加えてusageフックも使います。
ランタイムヘルパー
プラグインは、api.runtimeを通じて選択されたコアヘルパーにアクセスできます。TTSの場合:
textToSpeechは、ファイル / ボイスノートサーフェス向けの通常のコアTTS出力ペイロードを返します。- コアの
messages.tts設定とプロバイダー選択を使用します。 - PCM音声バッファー + サンプルレートを返します。プラグイン側でプロバイダー向けにリサンプリング / エンコードする必要があります。
listVoicesは、プロバイダーごとに任意です。ベンダー所有の音声ピッカーやセットアップフローに使ってください。- 音声一覧には、プロバイダー対応ピッカー向けに、locale、gender、personality tagなどのより豊富なメタデータを含められます。
- 電話対応は現時点でOpenAIとElevenLabsがサポートします。Microsoftはサポートしません。
api.registerSpeechProvider(...)を通じてspeech providerも登録できます。
- TTSポリシー、フォールバック、返信配信はコアに維持してください。
- ベンダー所有の合成挙動にはspeech providerを使ってください。
- レガシーMicrosoftの
edge入力は、microsoftprovider idへ正規化されます。 - 推奨される所有権モデルは企業指向です。OpenClawが これらのケイパビリティコントラクトを追加していくにつれ、1つのベンダープラグインが テキスト、音声、画像、将来のメディアプロバイダーを所有できます。
- オーケストレーション、フォールバック、config、チャネル配線はコアに維持してください。
- ベンダー挙動はプロバイダープラグインに維持してください。
- 加法的拡張は型付きのままであるべきです。新しい任意メソッド、新しい任意 結果フィールド、新しい任意ケイパビリティの形にしてください。
- 動画生成はすでに同じパターンに従います。
- コアがケイパビリティコントラクトとランタイムヘルパーを所有する
- ベンダープラグインが
api.registerVideoGenerationProvider(...)を登録する - 機能 / チャネルプラグインが
api.runtime.videoGeneration.*を消費する
api.runtime.mediaUnderstanding.*は、 画像 / 音声 / 動画理解向けの推奨共有サーフェスです。- コアのmedia-understanding音声設定(
tools.media.audio)とプロバイダーフォールバック順序を使用します。 - 文字起こし出力が生成されない場合(たとえばスキップ / 未対応入力)は、
{ text: undefined }を返します。 api.runtime.stt.transcribeAudioFile(...)は互換性エイリアスとして残っています。
api.runtime.subagentを通じてバックグラウンドsubagent実行も開始できます。
providerとmodelは、永続的なセッション変更ではなく、実行ごとの任意オーバーライドです。- OpenClawは、それらのオーバーライドフィールドを信頼された呼び出し元に対してのみ受け付けます。
- プラグイン所有のフォールバック実行については、運用者が
plugins.entries.<id>.subagent.allowModelOverride: trueで明示的にオプトインする必要があります。 - 信頼されたプラグインを特定の正規
provider/modelターゲットに制限するにはplugins.entries.<id>.subagent.allowedModelsを使い、任意ターゲットを明示的に許可するには"*"を使ってください。 - 信頼されていないプラグインのsubagent実行も動作しますが、オーバーライド要求は黙ってフォールバックされるのではなく拒否されます。
api.registerWebSearchProvider(...)を通じてWeb検索プロバイダーも登録できます。
注意:
- プロバイダー選択、認証情報解決、および共有リクエストセマンティクスはコアに維持してください。
- ベンダー固有検索トランスポートにはWeb検索プロバイダーを使ってください。
api.runtime.webSearch.*は、エージェントツールラッパーに依存せずに 検索挙動を必要とする機能 / チャネルプラグイン向けの推奨共有サーフェスです。
api.runtime.imageGeneration
generate(...): 設定された画像生成プロバイダーチェーンを使って画像を生成します。listProviders(...): 利用可能な画像生成プロバイダーとそのケイパビリティを一覧表示します。
Gateway HTTPルート
プラグインはapi.registerHttpRoute(...)でHTTPエンドポイントを公開できます。
path: gateway HTTPサーバー配下のルートパス。auth: 必須。通常のgateway認証を要求するには"gateway"、プラグイン管理の認証 / webhook検証には"plugin"を使います。match: 任意。"exact"(デフォルト)または"prefix"。replaceExisting: 任意。同じプラグインが自分自身の既存ルート登録を置き換えることを許可します。handler: ルートがリクエストを処理した場合はtrueを返します。
api.registerHttpHandler(...)は削除されており、プラグイン読み込みエラーになります。代わりにapi.registerHttpRoute(...)を使ってください。- プラグインルートは
authを明示的に宣言する必要があります。 - 同一の
path + match競合は、replaceExisting: trueがない限り拒否され、あるプラグインが別のプラグインのルートを置き換えることはできません。 authレベルが異なる重複ルートは拒否されます。exact/prefixのフォールスルーチェーンは同じauthレベル内にのみ保ってください。auth: "plugin"ルートは、運用者ランタイムスコープを自動では受け取りません。これはプラグイン管理のwebhook / 署名検証向けであり、特権Gatewayヘルパー呼び出し向けではありません。auth: "gateway"ルートはGatewayリクエストランタイムスコープ内で実行されますが、そのスコープは意図的に保守的です。- 共有シークレットbearer認証(
gateway.auth.mode = "token"/"password")では、呼び出し元がx-openclaw-scopesを送信しても、プラグインルートのランタイムスコープはoperator.writeに固定されます - 信頼されたID付きHTTPモード(たとえば
trusted-proxyや、プライベートingress上のgateway.auth.mode = "none")では、x-openclaw-scopesヘッダーが明示的に存在する場合にのみそれを尊重します - それらのID付きプラグインルートリクエストで
x-openclaw-scopesが存在しない場合、ランタイムスコープはoperator.writeへフォールバックします
- 共有シークレットbearer認証(
- 実践的なルール: gateway-authプラグインルートを暗黙の管理者サーフェスだと思わないでください。ルートが管理者専用挙動を必要とするなら、ID付き認証モードを要求し、明示的な
x-openclaw-scopesヘッダー契約を文書化してください。
Plugin SDK importパス
プラグイン作成時には、単一のopenclaw/plugin-sdk importではなく、
SDK subpathを使ってください。
- プラグイン登録プリミティブには
openclaw/plugin-sdk/plugin-entry。 - 汎用の共有プラグイン向けコントラクトには
openclaw/plugin-sdk/core。 - ルート
openclaw.jsonZod schema export(OpenClawSchema)にはopenclaw/plugin-sdk/config-schema。 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、およびopenclaw/plugin-sdk/webhook-ingressのような安定したチャネルプリミティブは、 共有setup / auth / reply / webhook 配線向けです。channel-inboundは、debounce、mentionマッチング、 envelope整形、および受信envelope context helperの共有ホームです。channel-setupは狭いoptional-install setupシームです。setup-runtimeは、setupEntry/ 遅延起動で使われるランタイム安全なsetupサーフェスであり、 import安全なsetup patch adapterを含みます。setup-adapter-runtimeはenv対応account-setup adapterシームです。setup-toolsは、小さなCLI / archive / docs helperシーム(formatCliCommand、detectBinary,extractArchive,resolveBrewExecutable,formatDocsLink,CONFIG_DIR)です。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-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、およびopenclaw/plugin-sdk/directory-runtimeのようなドメインsubpathは、 共有ランタイム / config helper向けです。telegram-command-configは、Telegramカスタム コマンド正規化 / 検証向けの狭い公開シームであり、 バンドル済みTelegramコントラクトサーフェスが一時的に利用不能な場合でも利用可能なままです。text-runtimeは、assistant-visible-text除去、 markdown render / chunking helper、redaction helper、directive-tag helper、およびsafe-text utilityを含む、 共有text / markdown / loggingシームです。- 承認固有チャネルシームでは、プラグイン上の1つの
approvalCapabilityコントラクトを優先してください。するとコアは、その1つのケイパビリティを通じて approval auth、delivery、render、およびnative-routing挙動を読み取り、 approval挙動を無関係なプラグインフィールドへ混ぜる必要がなくなります。 openclaw/plugin-sdk/channel-runtimeは非推奨で、 古いプラグイン向けの互換性shimとしてのみ残っています。新しいコードでは、 代わりにより狭い汎用プリミティブをimportするべきであり、repoコードでも このshimへの新規importを追加すべきではありません。- バンドル済み拡張の内部は非公開のままです。外部プラグインは
openclaw/plugin-sdk/*subpathのみを使うべきです。OpenClawのコア / テストコードは、index.js、api.js、runtime-api.js、setup-entry.js、およびlogin-qr-api.jsのような狭く限定されたファイルなど、プラグインパッケージルート配下の repo公開エントリポイントを使えます。コアまたは別拡張から、 プラグインパッケージのsrc/*をimportしてはいけません。 - repoエントリポイント分割:
<plugin-package-root>/api.jsはhelper / types barrel、<plugin-package-root>/runtime-api.jsはruntime-only barrel、<plugin-package-root>/index.jsはバンドル済みプラグインエントリー、<plugin-package-root>/setup-entry.jsはsetupプラグインエントリーです。 - 現在のバンドル済みプロバイダー例:
- Anthropicは、
wrapAnthropicProviderStream、beta-header helper、service_tier解析などのClaude stream helper向けにapi.js/contract-api.jsを使います。 - OpenAIは、provider builder、default-model helper、realtime provider builder向けに
api.jsを使います。 - OpenRouterは、そのprovider builderに加えてonboarding / config
helper向けに
api.jsを使い、register.runtime.jsは依然としてrepoローカル用途向けに 汎用plugin-sdk/provider-streamhelperを再exportできます。
- Anthropicは、
- facade読み込みされる公開エントリポイントは、利用可能な場合はアクティブな ランタイムconfigスナップショットを優先し、OpenClawがまだランタイム スナップショットを提供していない場合は、ディスク上の解決済みconfigファイルへフォールバックします。
- 汎用共有プリミティブは、引き続き推奨される公開SDKコントラクトです。
バンドル済みチャネルブランド付きhelperシームの小さな予約済み互換セットは今も存在します。これらは
バンドル保守 / 互換性シームとして扱い、新しい
サードパーティimportターゲットとしては扱わないでください。新しいクロスチャネルコントラクトは、
引き続き汎用
plugin-sdk/*subpathまたはプラグインローカルのapi.js/runtime-api.jsbarrelに置くべきです。
- 新しいコードでは、ルートの
openclaw/plugin-sdkbarrelは避けてください。 - まず狭い安定プリミティブを優先してください。新しいsetup / pairing / reply /
feedback / contract / inbound / threading / command / secret-input / webhook / infra /
allowlist / status / message-tool subpathが、新しい
バンドル済みおよび外部プラグイン作業向けの意図されたコントラクトです。
target解析 / マッチングは
openclaw/plugin-sdk/channel-targetsに属します。 message action gateおよびreaction message-id helperはopenclaw/plugin-sdk/channel-actionsに属します。 - バンドル済み拡張固有helper barrelは、デフォルトでは安定していません。
あるhelperがバンドル済み拡張にしか必要ない場合は、
openclaw/plugin-sdk/<extension>へ昇格させるのではなく、 その拡張のローカルapi.jsまたはruntime-api.jsシームの背後に保ってください。 - 新しい共有helperシームは、チャネルブランド付きではなく汎用であるべきです。共有target
解析は
openclaw/plugin-sdk/channel-targetsに属し、チャネル固有 内部は、そのプラグイン所有のローカルapi.jsまたはruntime-api.jsシームの背後に留まります。 image-generation、media-understanding、speechのようなケイパビリティ固有subpathは、 バンドル済み / ネイティブプラグインが現在それらを使っているため存在します。 それらが存在すること自体は、exportされたすべてのhelperが 長期的に凍結された外部コントラクトであることを意味しません。
Messageツールschema
プラグインは、チャネル固有のdescribeMessageTool(...) schema
寄与を所有するべきです。プロバイダー固有フィールドは、共有コアではなく
プラグイン内に保持してください。
共有の移植可能schemaフラグメントについては、
openclaw/plugin-sdk/channel-actions経由でexportされる汎用helperを再利用してください。
- ボタングリッド形式のpayloadには
createMessageToolButtonsSchema() - 構造化カードpayloadには
createMessageToolCardSchema()
チャネルtarget解決
チャネルプラグインは、チャネル固有のtargetセマンティクスを所有するべきです。共有 outbound hostは汎用のままにし、メッセージングadapterサーフェスをプロバイダールールに使ってください。messaging.inferTargetChatType({ to })は、正規化されたtargetを directory lookup前にdirect、group、またはchannelとして扱うべきかを決定します。messaging.targetResolver.looksLikeId(raw, normalized)は、ある入力が directory searchではなく、明示的 / ネイティブtarget id解決へ直接進むべきかどうかをコアに伝えます。messaging.targetResolver.resolveTarget(...)は、正規化後または directory miss後に、コアが最終的なプロバイダー所有解決を必要とする場合のプラグイン側フォールバックです。messaging.resolveOutboundSessionRoute(...)は、target解決後の プロバイダー固有セッションルート構築を所有します。
- peer / group検索前に行うべきカテゴリ判定には
inferTargetChatTypeを使う - 「これを明示的 / ネイティブtarget idとして扱う」判定には
looksLikeIdを使う resolveTargetは、広範なdirectory searchではなく、 プロバイダー固有の正規化フォールバックに使う- chat id、thread id、JID、handle、room idのようなプロバイダーネイティブidは、
汎用SDKフィールドではなく、
target値またはプロバイダー固有パラメーター内に保持する
configベースのdirectory
configからdirectoryエントリーを導出するプラグインは、そのロジックを プラグイン内に保持し、openclaw/plugin-sdk/directory-runtimeの共有helperを再利用するべきです。
これは、あるチャネルが次のようなconfigベースpeer / groupを必要とする場合に使ってください。
- allowlist駆動のDM peer
- 設定されたchannel / group map
- accountスコープの静的directoryフォールバック
directory-runtimeの共有helperは、汎用操作のみを扱います。
- クエリフィルタリング
- limit適用
- dedupe / 正規化helper
ChannelDirectoryEntry[]の構築
プロバイダーカタログ
プロバイダープラグインは、registerProvider({ catalog: { run(...) { ... } } })で推論向けモデルカタログを定義できます。
catalog.run(...)は、OpenClawがmodels.providersへ書き込むのと同じ形状を返します。
- 1つのproviderエントリーには
{ provider } - 複数のproviderエントリーには
{ providers }
catalogを使ってください。
catalog.orderは、プラグインのカタログがOpenClawの
組み込み暗黙プロバイダーに対してどのタイミングでマージされるかを制御します。
simple: 単純なAPIキーまたはenv駆動プロバイダーprofile: auth profileが存在すると現れるプロバイダーpaired: 複数の関連providerエントリーを合成するプロバイダーlate: 最終パス。他の暗黙プロバイダーの後
discoveryはレガシーエイリアスとして引き続き動作しますcatalogとdiscoveryの両方が登録されている場合、OpenClawはcatalogを使います
読み取り専用チャネル検査
プラグインがチャネルを登録する場合は、resolveAccount(...)と並んで
plugin.config.inspectAccount(cfg, accountId)の実装を優先してください。
理由:
resolveAccount(...)はランタイム経路です。認証情報が 完全に具体化されていることを前提にでき、必要なシークレットが不足していれば 即座に失敗して構いません。openclaw status、openclaw status --all、openclaw channels status、openclaw channels resolve、およびdoctor / config 修復フローのような読み取り専用コマンド経路では、 設定を説明するだけのためにランタイム認証情報を具体化する必要はありません。
inspectAccount(...)の挙動:
- 記述的なaccount状態のみを返す
enabledとconfiguredを保持する- 関連する場合は、認証情報のsource / statusフィールドを含める。例:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- 読み取り専用の利用可能性を報告するためだけに、生のtoken値を返す必要はありません。
tokenStatus: "available"(および対応するsourceフィールド)を返せば、 status系コマンドには十分です。 - 認証情報がSecretRef経由で設定されているが、現在のコマンド経路では利用できない場合は
configured_unavailableを使う
パッケージパック
プラグインディレクトリには、openclaw.extensionsを含むpackage.jsonを置けます。
name/<fileBase>になります。
プラグインがnpm依存関係をimportする場合は、そのディレクトリ内に
node_modulesが使えるようインストールしてください(npm install / pnpm install)。
セキュリティガードレール: すべてのopenclaw.extensionsエントリーは、
symlink解決後もプラグインディレクトリ内に留まる必要があります。パッケージディレクトリの外へ
逃げるエントリーは拒否されます。
セキュリティ上の注意: openclaw plugins installは、プラグイン依存関係を
npm install --omit=dev --ignore-scriptsでインストールします(ライフサイクルスクリプトなし、ランタイムでdev dependencyなし)。プラグイン依存
ツリーは「pure JS/TS」に保ち、
postinstallビルドを必要とするパッケージは避けてください。
任意: openclaw.setupEntryは軽量のsetup専用モジュールを指せます。
OpenClawが無効なチャネルプラグイン向けにsetupサーフェスを必要とする場合、または
チャネルプラグインが有効でも未設定の場合、
完全なプラグインエントリーの代わりにsetupEntryを読み込みます。これにより、
メインプラグインエントリーがツール、フック、その他のランタイム専用
コードも配線している場合に、起動とsetupを軽く保てます。
任意: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
は、チャネルがすでに設定済みであっても、
gatewayのpre-listen起動フェーズ中にチャネルプラグインを同じsetupEntry経路へ
オプトインさせることができます。
これを使うのは、setupEntryがgatewayがlisten開始前に
存在すべき起動サーフェスを完全にカバーしている場合だけにしてください。
実際には、setup entryが起動に依存する
すべてのチャネル所有ケイパビリティを登録する必要があることを意味します。たとえば:
- チャネル登録そのもの
- gatewayがlisten開始前に利用可能であるべき任意のHTTPルート
- 同じウィンドウ内で存在すべき任意のgatewayメソッド、ツール、またはサービス
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.*へ昇格する必要があるときに
そのサーフェスを使います。現在のバンドル例はMatrixです。これは、
名前付きaccountがすでに存在する場合にauth / bootstrapキーだけを
名前付き昇格accountへ移動し、
常にaccounts.defaultを作成するのではなく、
設定済みの非canonical default-accountキーを保持できます。
これらのsetup patch adapterにより、バンドル済みコントラクトサーフェス検出は遅延のままです。import
時は軽量に保たれ、promotionサーフェスはモジュールimport時に
バンドル済みチャネル起動へ再突入するのではなく、最初の使用時にのみ読み込まれます。
それらの起動サーフェスにgateway RPCメソッドが含まれる場合は、
プラグイン固有プレフィックスに保ってください。コア管理namespace(config.*、
exec.approvals.*、wizard.*、update.*)は引き続き予約済みであり、
プラグインがより狭いスコープを要求しても、常にoperator.adminへ解決されます。
例:
チャネルカタログメタデータ
チャネルプラグインは、openclaw.channelを通じてsetup / discoveryメタデータを、
openclaw.installを通じてインストールヒントを告知できます。これによりコアのカタログは
データフリーに保たれます。
例:
openclaw.channelフィールド:
detailLabel: より豊かなcatalog / statusサーフェス向けの二次ラベルdocsLabel: docsリンクのリンクテキスト上書きpreferOver: このcatalogエントリーが上位に置くべき低優先度plugin / channel idselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: selection-surfaceの文言制御markdownCapable: outbound整形判断のために、チャネルをmarkdown対応として示すshowConfigured:falseに設定すると、configured-channel一覧サーフェスからそのチャネルを隠すquickstartAllowFrom: チャネルを標準クイックスタートallowFromフローへオプトインするforceAccountBinding: accountが1つしかなくても明示的account 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"も受け付けます。
コンテキストエンジンプラグイン
コンテキストエンジンプラグインは、取り込み、組み立て、 圧縮のためのセッションコンテキストオーケストレーションを所有します。 プラグインからapi.registerContextEngine(id, factory)で登録し、
アクティブエンジンはplugins.slots.contextEngineで選択します。
これは、プラグインがデフォルトのコンテキスト
パイプラインを単にmemory searchやフックで追加するだけでなく、
置き換えたり拡張したりする必要がある場合に使ってください。
compact()
は実装し、明示的に委譲してください。
新しいケイパビリティの追加
プラグインが現在のAPIに収まらない挙動を必要とする場合は、 プライベートな直接参照でプラグインシステムを迂回しないでください。不足しているケイパビリティを追加してください。 推奨される順序:- コアコントラクトを定義する コアが所有すべき共有挙動を決めてください。ポリシー、フォールバック、configマージ、 ライフサイクル、チャネル向けセマンティクス、およびランタイムヘルパーの形状です。
- 型付きプラグイン登録 / ランタイムサーフェスを追加する
最小限で有用な
型付きケイパビリティサーフェスで
OpenClawPluginApiおよび / またはapi.runtimeを拡張します。 - コア + チャネル / 機能コンシューマーを配線する チャネルと機能プラグインは、ベンダー実装を直接importするのではなく、 コアを通じて新しいケイパビリティを消費するべきです。
- ベンダー実装を登録する その後、ベンダープラグインがそのケイパビリティに対してバックエンドを登録します。
- コントラクトカバレッジを追加する 所有権と登録形状が時間とともに明示的に保たれるよう、テストを追加します。
ケイパビリティチェックリスト
新しいケイパビリティを追加するとき、実装では通常、 これらのサーフェスをまとめて触るべきです。src/<capability>/types.tsのコアコントラクト型src/<capability>/runtime.tsのコアランナー / ランタイムヘルパーsrc/plugins/types.tsのプラグインAPI登録サーフェスsrc/plugins/registry.tsのプラグインレジストリ配線- 機能 / チャネル
プラグインがそれを消費する必要がある場合の
src/plugins/runtime/*内のプラグインランタイム公開 src/test-utils/plugin-registration.tsのcapture / test helpersrc/plugins/contracts/registry.tsの所有権 / コントラクト検証docs/の運用者 / プラグイン向けドキュメント
ケイパビリティテンプレート
最小パターン:- コアがケイパビリティコントラクト + オーケストレーションを所有する
- ベンダープラグインがベンダー実装を所有する
- 機能 / チャネルプラグインがランタイムヘルパーを消費する
- コントラクトテストが所有権を明示的に保つ