Plugins

Pluginの構築

Plugins は OpenClaw に新しい機能を追加します。チャネル、モデルプロバイダー、 音声、リアルタイム文字起こし、リアルタイム音声、メディア理解、画像 生成、動画生成、Web 取得、Web 検索、エージェントツール、またはそれらの 任意の組み合わせです。

Plugin を OpenClaw リポジトリに追加する必要はありません。 ClawHub に公開すると、ユーザーは openclaw plugins install clawhub:<package-name> でインストールできます。プレフィックスなしのパッケージ指定も、ローンチ移行中は引き続き npm から インストールされます。

前提条件

  • Node >= 22 とパッケージマネージャー (npm または pnpm)
  • TypeScript (ESM) に慣れていること
  • リポジトリ内 Plugin の場合: リポジトリをクローンし、pnpm install が完了していること。ソース チェックアウトでの Plugin 開発は pnpm のみです。OpenClaw は extensions/* ワークスペースパッケージからバンドル済み Plugins を読み込むためです。

どの種類の Plugin か?

オンボーディング/セットアップの実行時にインストール済みであることが保証されないチャネルPluginでは、 openclaw/plugin-sdk/channel-setupcreateOptionalChannelSetupSurface(...) を使用します。 これはセットアップアダプターとウィザードのペアを生成し、 インストール要件を通知し、Plugin がインストールされるまで実際の設定書き込みを失敗として閉じます。

クイックスタート: ツールPlugin

このウォークスルーでは、エージェントツールを登録する最小限の Plugin を作成します。チャネル およびプロバイダーPlugins には、上記にリンクされた専用ガイドがあります。

  • パッケージとマニフェストを作成する

    {
    "name": "@myorg/openclaw-my-plugin",
    "version": "1.0.0",
    "type": "module",
    "openclaw": {
      "extensions": ["./index.ts"],
      "compat": {
        "pluginApi": ">=2026.3.24-beta.2",
        "minGatewayVersion": "2026.3.24-beta.2"
      },
      "build": {
        "openclawVersion": "2026.3.24-beta.2",
        "pluginSdkVersion": "2026.3.24-beta.2"
      }
    }
    }
    
    {
    "id": "my-plugin",
    "name": "My Plugin",
    "description": "Adds a custom tool to OpenClaw",
    "contracts": {
      "tools": ["my_tool"]
    },
    "activation": {
      "onStartup": true
    },
    "configSchema": {
      "type": "object",
      "additionalProperties": false
    }
    }
    

    設定がない場合でも、すべての Plugin にはマニフェストが必要です。ランタイム登録ツールは contracts.tools に列挙する必要があります。これにより、OpenClaw はすべての Plugin ランタイムを読み込まずに、 所有する Plugin を検出できます。Plugins は activation.onStartup も意図を持って宣言するべきです。この例では true に設定しています。完全なスキーマについては マニフェスト を参照してください。正規の ClawHub 公開スニペットは docs/snippets/plugin-publish/ にあります。

  • エントリポイントを書く

    // index.ts
    import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
    import { Type } from "@sinclair/typebox";
    
    export default definePluginEntry({
      id: "my-plugin",
      name: "My Plugin",
      description: "Adds a custom tool to OpenClaw",
      register(api) {
        api.registerTool({
          name: "my_tool",
          description: "Do a thing",
          parameters: Type.Object({ input: Type.String() }),
          async execute(_id, params) {
            return { content: [{ type: "text", text: `Got: ${params.input}` }] };
          },
        });
      },
    });
    

    definePluginEntry は非チャネルPlugins 用です。チャネルでは defineChannelPluginEntry を使用します - チャネルPlugins を参照してください。 すべてのエントリポイントオプションについては、エントリポイント を参照してください。

  • テストして公開する

    外部Plugins: ClawHub で検証して公開し、その後インストールします。

    clawhub package publish your-org/your-plugin --dry-run
    clawhub package publish your-org/your-plugin
    openclaw plugins install clawhub:@myorg/openclaw-my-plugin
    

    @myorg/openclaw-my-plugin のようなプレフィックスなしのパッケージ指定は、ローンチ移行中に npm からインストールされます。 ClawHub 解決を使いたい場合は clawhub: を使用します。

    リポジトリ内 Plugins: バンドル済み Plugin ワークスペースツリーの下に配置します - 自動的に検出されます。

    pnpm test -- <bundled-plugin-root>/my-plugin/
    
  • Plugin の機能

    単一の Plugin は api オブジェクトを介して任意の数の機能を登録できます。

    機能 登録メソッド 詳細ガイド
    テキスト推論 (LLM) api.registerProvider(...) プロバイダーPlugins
    CLI 推論バックエンド api.registerCliBackend(...) CLI バックエンドPlugins
    チャネル / メッセージング api.registerChannel(...) チャネルPlugins
    音声 (TTS/STT) api.registerSpeechProvider(...) プロバイダーPlugins
    リアルタイム文字起こし api.registerRealtimeTranscriptionProvider(...) プロバイダーPlugins
    リアルタイム音声 api.registerRealtimeVoiceProvider(...) プロバイダーPlugins
    メディア理解 api.registerMediaUnderstandingProvider(...) プロバイダーPlugins
    画像生成 api.registerImageGenerationProvider(...) プロバイダーPlugins
    音楽生成 api.registerMusicGenerationProvider(...) プロバイダーPlugins
    動画生成 api.registerVideoGenerationProvider(...) プロバイダーPlugins
    Web 取得 api.registerWebFetchProvider(...) プロバイダーPlugins
    Web 検索 api.registerWebSearchProvider(...) プロバイダーPlugins
    ツール結果ミドルウェア api.registerAgentToolResultMiddleware(...) SDK 概要
    エージェントツール api.registerTool(...) 以下
    カスタムコマンド api.registerCommand(...) エントリポイント
    Plugin フック api.on(...) Plugin フック
    内部イベントフック api.registerHook(...) エントリポイント
    HTTP ルート api.registerHttpRoute(...) 内部構造
    CLI サブコマンド api.registerCli(...) エントリポイント

    完全な登録 API については、SDK 概要 を参照してください。

    バンドル済み Plugins は、モデルが出力を見る前に非同期ツール結果の書き換えが必要な場合、 api.registerAgentToolResultMiddleware(...) を使用できます。 対象ランタイムを contracts.agentToolResultMiddleware に宣言します。例: ["pi", "codex"]。これは信頼済みのバンドル済み Plugin 向けの継ぎ目です。外部 Plugins は、この機能に対する明示的な信頼ポリシーが OpenClaw に追加されるまでは、通常の OpenClaw Plugin フックを優先してください。

    Plugin がカスタム Gateway RPC メソッドを登録する場合は、それらを Plugin 固有のプレフィックス上に置いてください。コア管理名前空間 (config.*, exec.approvals.*, wizard.*, update.*) は予約済みのままで、Plugin がより狭いスコープを要求しても常に operator.admin に解決されます。

    覚えておくべきフックガードのセマンティクス:

    • before_tool_call: { block: true } は終端であり、低優先度のハンドラーを停止します。
    • before_tool_call: { block: false } は決定なしとして扱われます。
    • before_tool_call: { requireApproval: true } はエージェントの実行を一時停止し、exec 承認オーバーレイ、Telegram ボタン、Discord インタラクション、または任意のチャネルの /approve コマンドを介してユーザーに承認を求めます。
    • before_install: { block: true } は終端であり、低優先度のハンドラーを停止します。
    • before_install: { block: false } は決定なしとして扱われます。
    • message_sending: { cancel: true } は終端であり、低優先度のハンドラーを停止します。
    • message_sending: { cancel: false } は決定なしとして扱われます。
    • message_received: 受信スレッド/トピックのルーティングが必要な場合は、型付きの threadId フィールドを優先してください。チャネル固有の追加情報には metadata を使用します。
    • message_sending: チャネル固有のメタデータキーよりも、型付きの replyToId / threadId ルーティングフィールドを優先してください。

    /approve コマンドは、範囲付きフォールバックで exec 承認と Plugin 承認の両方を処理します。exec 承認 ID が見つからない場合、OpenClaw は同じ ID を Plugin 承認で再試行します。Plugin 承認の転送は、設定内の approvals.plugin で独立して構成できます。

    カスタム承認配管で同じ範囲付きフォールバックケースを検出する必要がある場合は、 承認期限切れ文字列を手動で照合するのではなく、 openclaw/plugin-sdk/error-runtimeisApprovalNotFoundError を優先してください。

    例とフックリファレンスについては、Plugin フック を参照してください。

    エージェントツールの登録

    ツールは LLM が呼び出せる型付き関数です。必須 (常に 利用可能) または任意 (ユーザーのオプトイン) にできます。

    register(api) {
      // Required tool - always available
      api.registerTool({
        name: "my_tool",
        description: "Do a thing",
        parameters: Type.Object({ input: Type.String() }),
        async execute(_id, params) {
          return { content: [{ type: "text", text: params.input }] };
        },
      });
    
      // Optional tool - user must add to allowlist
      api.registerTool(
        {
          name: "workflow_tool",
          description: "Run a workflow",
          parameters: Type.Object({ pipeline: Type.String() }),
          async execute(_id, params) {
            return { content: [{ type: "text", text: params.pipeline }] };
          },
        },
        { optional: true },
      );
    }
    

    api.registerTool(...) で登録されるすべてのツールは、Plugin マニフェストでも宣言する必要があります。

    {
      "contracts": {
        "tools": ["my_tool", "workflow_tool"]
      },
      "toolMetadata": {
        "workflow_tool": {
          "optional": true
        }
      }
    }
    

    OpenClaw は登録済みツールから検証済み descriptor を取得してキャッシュするため、 Plugin はマニフェスト内で description やスキーマデータを重複させません。 マニフェスト契約は所有権と検出のみを宣言します。実行時は引き続き、 ライブ登録済みツール実装を呼び出します。 api.registerTool(..., { optional: true }) で登録したツールには toolMetadata.<tool>.optional: true を設定し、ツールが明示的に allowlist に追加されるまで OpenClaw がその Plugin runtime を読み込まずに済むようにします。

    ユーザーは config で optional tools を有効にします。

    {
      tools: { allow: ["workflow_tool"] },
    }
    
    • ツール名は core tools と衝突してはいけません(衝突はスキップされます)
    • parameters の欠落を含む不正な登録オブジェクトを持つツールは、agent runs を壊す代わりにスキップされ、Plugin diagnostics に報告されます
    • 副作用や追加のバイナリ要件があるツールには optional: true を使います
    • ユーザーは Plugin id を tools.allow に追加することで、その Plugin のすべてのツールを有効にできます

    CLI コマンドの登録

    Plugin は api.registerCli で root openclaw コマンドグループを追加できます。 各 top-level command root に descriptors を指定すると、OpenClaw はすべての Plugin runtime を eager に読み込まずにコマンドを表示してルーティングできます。

    register(api) {
      api.registerCli(
        ({ program }) => {
          const demo = program
            .command("demo-plugin")
            .description("Run demo plugin commands");
    
          demo
            .command("ping")
            .description("Check that the plugin CLI is executable")
            .action(() => {
              console.log("demo-plugin:pong");
            });
        },
        {
          descriptors: [
            {
              name: "demo-plugin",
              description: "Run demo plugin commands",
              hasSubcommands: true,
            },
          ],
        },
      );
    }
    

    インストール後、runtime 登録を検証してコマンドを実行します。

    openclaw plugins inspect demo-plugin --runtime --json
    openclaw demo-plugin ping
    

    import 規約

    常に focused な openclaw/plugin-sdk/<subpath> パスから import します。

    
    
    // Wrong: monolithic root (deprecated, will be removed)
    
    

    完全な subpath reference については、SDK 概要 を参照してください。

    Plugin 内では、internal imports に local barrel files(api.tsruntime-api.ts)を使い、 自分自身の Plugin を SDK path 経由で import しないでください。

    provider Plugin では、その seam が真に generic でない限り、provider 固有の helpers は その package-root barrels に置いてください。現在の bundled examples は次のとおりです。

    • Anthropic: Claude stream wrappers と service_tier / beta helpers
    • OpenAI: provider builders、default-model helpers、realtime providers
    • OpenRouter: provider builder とオンボーディング/config helpers

    helper が 1 つの bundled provider package 内でしか有用でない場合は、 openclaw/plugin-sdk/* に昇格させるのではなく、その package-root seam に保持してください。

    一部の生成済み openclaw/plugin-sdk/<bundled-id> helper seams は、tracked owner usage がある場合の bundled-plugin maintenance のためにまだ存在します。新しい third-party Plugin の既定パターンではなく、 予約済みの surfaces として扱ってください。

    送信前チェックリスト

    OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s package.json に正しい openclaw metadata がある OPENCLAW_DOCS_MARKER:calloutClose:

    OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s openclaw.plugin.json マニフェストが存在し、有効である OPENCLAW_DOCS_MARKER:calloutClose:

    OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s entry point が defineChannelPluginEntry または definePluginEntry を使っている OPENCLAW_DOCS_MARKER:calloutClose:

    OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s すべての import が focused な plugin-sdk/<subpath> パスを使っている OPENCLAW_DOCS_MARKER:calloutClose: