Building plugins

ساخت Pluginها

Edit source

Pluginها OpenClaw را با قابلیت‌های تازه گسترش می‌دهند: کانال‌ها، ارائه‌دهندگان مدل، گفتار، رونویسی بلادرنگ، صدای بلادرنگ، درک رسانه، تولید تصویر، تولید ویدئو، دریافت وب، جست‌وجوی وب، ابزارهای عامل، یا هر ترکیبی از آن‌ها.

لازم نیست Plugin خود را به مخزن OpenClaw اضافه کنید. در ClawHub منتشر کنید و کاربران با openclaw plugins install clawhub:<package-name> نصب می‌کنند. مشخصات خام بسته همچنان در دوره گذار راه‌اندازی از npm نصب می‌شوند.

پیش‌نیازها

  • Node >= 22 و یک مدیر بسته (npm یا pnpm)
  • آشنایی با TypeScript (ESM)
  • برای Pluginهای داخل مخزن: مخزن clone شده و pnpm install انجام شده باشد. توسعه Plugin با checkout منبع فقط با pnpm است، چون OpenClaw، Pluginهای بسته‌بندی‌شده را از بسته‌های workspace در extensions/* بارگذاری می‌کند.

چه نوع Pluginی؟

برای یک Plugin کانال که تضمین نمی‌شود هنگام اجرای onboarding/setup نصب شده باشد، از createOptionalChannelSetupSurface(...) در openclaw/plugin-sdk/channel-setup استفاده کنید. این یک جفت آداپتور setup + wizard می‌سازد که نیاز نصب را اعلام می‌کند و تا وقتی Plugin نصب نشده باشد، در نوشتن config واقعی بسته شکست می‌خورد.

شروع سریع: Plugin ابزار

این راهنما یک Plugin حداقلی می‌سازد که یک ابزار عامل را ثبت می‌کند. Pluginهای کانال و ارائه‌دهنده راهنماهای اختصاصی دارند که بالاتر لینک شده‌اند.

  • Create the package and manifest

    package.json
    {"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"  }}}
    openclaw.plugin.json
    {"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 به یک manifest نیاز دارد، حتی اگر config نداشته باشد. ابزارهایی که در runtime ثبت می‌شوند باید در contracts.tools فهرست شوند تا OpenClaw بتواند Plugin مالک را بدون بارگذاری runtime همه Pluginها کشف کند. Pluginها همچنین باید activation.onStartup را آگاهانه اعلام کنند. این مثال آن را روی true تنظیم می‌کند. برای schema کامل، Manifest را ببینید. snippetهای canonical انتشار ClawHub در docs/snippets/plugin-publish/ قرار دارند.

  • Write the entry point

    typescript
    // index.tsimport { 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 برای Pluginهای غیرکانالی است. برای کانال‌ها، از defineChannelPluginEntry استفاده کنید - Channel Plugins را ببینید. برای گزینه‌های کامل entry point، Entry Points را ببینید.

  • Test and publish

    Pluginهای خارجی: با ClawHub اعتبارسنجی و منتشر کنید، سپس نصب کنید:

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

    مشخصات خام بسته مانند @myorg/openclaw-my-plugin در دوره گذار راه‌اندازی از npm نصب می‌شوند. وقتی resolve از ClawHub را می‌خواهید، از clawhub: استفاده کنید.

    Pluginهای داخل مخزن: زیر درخت workspace Pluginهای بسته‌بندی‌شده قرار دهید - خودکار کشف می‌شود.

    bash
    pnpm test -- <bundled-plugin-root>/my-plugin/
  • قابلیت‌های Plugin

    یک Plugin می‌تواند از طریق شیء api هر تعداد قابلیت را ثبت کند:

    قابلیت روش ثبت راهنمای تفصیلی
    استنتاج متن (LLM) api.registerProvider(...) Provider Plugins
    backend استنتاج CLI api.registerCliBackend(...) CLI Backend Plugins
    کانال / پیام‌رسانی api.registerChannel(...) Channel Plugins
    گفتار (TTS/STT) api.registerSpeechProvider(...) Provider Plugins
    رونویسی بلادرنگ api.registerRealtimeTranscriptionProvider(...) Provider Plugins
    صدای بلادرنگ api.registerRealtimeVoiceProvider(...) Provider Plugins
    درک رسانه api.registerMediaUnderstandingProvider(...) Provider Plugins
    تولید تصویر api.registerImageGenerationProvider(...) Provider Plugins
    تولید موسیقی api.registerMusicGenerationProvider(...) Provider Plugins
    تولید ویدئو api.registerVideoGenerationProvider(...) Provider Plugins
    دریافت وب api.registerWebFetchProvider(...) Provider Plugins
    جست‌وجوی وب api.registerWebSearchProvider(...) Provider Plugins
    middleware نتیجه ابزار api.registerAgentToolResultMiddleware(...) SDK Overview
    ابزارهای عامل api.registerTool(...) پایین
    commandهای سفارشی api.registerCommand(...) Entry Points
    hookهای Plugin api.on(...) Plugin hooks
    hookهای رویداد داخلی api.registerHook(...) Entry Points
    مسیرهای HTTP api.registerHttpRoute(...) Internals
    subcommandهای CLI api.registerCli(...) Entry Points

    برای API کامل ثبت، SDK Overview را ببینید.

    Pluginهای بسته‌بندی‌شده می‌توانند وقتی به بازنویسی async نتیجه ابزار پیش از دیده شدن خروجی توسط مدل نیاز دارند، از api.registerAgentToolResultMiddleware(...) استفاده کنند. runtimeهای هدف را در contracts.agentToolResultMiddleware اعلام کنید، برای مثال ["pi", "codex"]. این یک seam مورد اعتماد برای Pluginهای بسته‌بندی‌شده است؛ Pluginهای خارجی باید hookهای معمول OpenClaw Plugin را ترجیح دهند، مگر اینکه OpenClaw برای این قابلیت یک سیاست اعتماد صریح اضافه کند.

    اگر Plugin شما روش‌های RPC سفارشی Gateway ثبت می‌کند، آن‌ها را روی یک پیشوند اختصاصی Plugin نگه دارید. namespaceهای ادمین core (config.*, exec.approvals.*, wizard.*, update.*) رزرو می‌مانند و همیشه به operator.admin resolve می‌شوند، حتی اگر یک Plugin scope محدودتری بخواهد.

    معنای guard hookها که باید در نظر داشته باشید:

    • before_tool_call: { block: true } نهایی است و handlerهای با اولویت پایین‌تر را متوقف می‌کند.
    • before_tool_call: { block: false } به‌عنوان نبود تصمیم تلقی می‌شود.
    • before_tool_call: { requireApproval: true } اجرای عامل را pause می‌کند و از کاربر از طریق overlay تأیید exec، دکمه‌های Telegram، interactionهای Discord، یا command /approve در هر کانالی درخواست تأیید می‌کند.
    • before_install: { block: true } نهایی است و handlerهای با اولویت پایین‌تر را متوقف می‌کند.
    • before_install: { block: false } به‌عنوان نبود تصمیم تلقی می‌شود.
    • message_sending: { cancel: true } نهایی است و handlerهای با اولویت پایین‌تر را متوقف می‌کند.
    • message_sending: { cancel: false } به‌عنوان نبود تصمیم تلقی می‌شود.
    • message_received: وقتی به routing thread/topic ورودی نیاز دارید، فیلد typed threadId را ترجیح دهید. metadata را برای موارد اضافی مختص کانال نگه دارید.
    • message_sending: فیلدهای routing typed یعنی replyToId / threadId را به کلیدهای metadata مختص کانال ترجیح دهید.

    command /approve هم تأییدهای exec و هم Plugin را با fallback محدود مدیریت می‌کند: وقتی id تأیید exec پیدا نشود، OpenClaw همان id را در تأییدهای Plugin دوباره امتحان می‌کند. forwarding تأیید Plugin را می‌توان به‌طور مستقل از طریق approvals.plugin در config پیکربندی کرد.

    اگر plumbing تأیید سفارشی نیاز دارد همان حالت fallback محدود را تشخیص دهد، به‌جای matching دستی رشته‌های انقضای تأیید، isApprovalNotFoundError را از openclaw/plugin-sdk/error-runtime ترجیح دهید.

    برای مثال‌ها و مرجع hook، Plugin hooks را ببینید.

    ثبت ابزارهای عامل

    ابزارها توابع typed هستند که LLM می‌تواند فراخوانی کند. آن‌ها می‌توانند الزامی باشند (همیشه در دسترس) یا اختیاری باشند (opt-in کاربر):

    typescript
    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 },  );}

    کارخانه‌های ابزار یک شیء زمینه‌ای تامین‌شده توسط زمان اجرا دریافت می‌کنند. وقتی یک ابزار نیاز دارد مدل فعال در نوبت فعلی را ثبت، نمایش، یا خود را با آن سازگار کند، از ctx.activeModel استفاده کنید. این شیء می‌تواند شامل provider، modelId و modelRef باشد. آن را فرادادهٔ اطلاعاتی زمان اجرا در نظر بگیرید، نه یک مرز امنیتی در برابر اپراتور محلی، کد Plugin نصب‌شده، یا زمان اجرای تغییریافتهٔ OpenClaw. برای ابزارهای محلی حساس، opt-in صریح Plugin یا اپراتور را نگه دارید و وقتی فرادادهٔ مدل فعال موجود نیست یا مناسب نیست، به‌صورت بسته شکست بخورید.

    هر ابزاری که با api.registerTool(...) ثبت می‌شود باید در manifest Plugin نیز اعلام شود:

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

    OpenClaw توصیفگر اعتبارسنجی‌شده را از ابزار ثبت‌شده ثبت و cache می‌کند، بنابراین Pluginها داده‌های description یا schema را در manifest تکرار نمی‌کنند. قرارداد manifest فقط مالکیت و کشف را اعلام می‌کند؛ اجرا همچنان پیاده‌سازی زندهٔ ابزار ثبت‌شده را فراخوانی می‌کند. برای ابزارهایی که با api.registerTool(..., { optional: true }) ثبت شده‌اند، مقدار toolMetadata.<tool>.optional: true را تنظیم کنید تا OpenClaw بتواند تا زمانی که ابزار به‌صراحت allowlist نشده است، از بارگذاری زمان اجرای آن Plugin خودداری کند.

    کاربران ابزارهای اختیاری را در پیکربندی فعال می‌کنند:

    json5
    {  tools: { allow: ["workflow_tool"] },}
    • نام ابزارها نباید با ابزارهای core تداخل داشته باشد (تداخل‌ها نادیده گرفته می‌شوند)
    • ابزارهایی با اشیای ثبت‌نام بدشکل، از جمله نبود parameters، به‌جای شکستن اجرای agent، نادیده گرفته می‌شوند و در diagnostics مربوط به Plugin گزارش می‌شوند
    • برای ابزارهایی که اثر جانبی یا نیازمندی binary اضافی دارند، از optional: true استفاده کنید
    • کاربران می‌توانند با افزودن شناسهٔ Plugin به tools.allow همهٔ ابزارهای یک Plugin را فعال کنند

    ثبت فرمان‌های CLI

    Pluginها می‌توانند با api.registerCli گروه‌های فرمان ریشهٔ openclaw اضافه کنند. برای هر ریشهٔ فرمان سطح بالا، descriptors ارائه کنید تا OpenClaw بتواند بدون بارگذاری مشتاقانهٔ زمان اجرای هر Plugin، فرمان را نمایش دهد و مسیریابی کند.

    typescript
    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,        },      ],    },  );}

    پس از نصب، ثبت زمان اجرا را بررسی و فرمان را اجرا کنید:

    bash
    openclaw plugins inspect demo-plugin --runtime --jsonopenclaw demo-plugin ping

    قراردادهای import

    همیشه از مسیرهای متمرکز openclaw/plugin-sdk/<subpath> import کنید:

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

    برای مرجع کامل subpath، نمای کلی SDK را ببینید.

    درون Plugin خود، برای importهای داخلی از فایل‌های barrel محلی (api.ts، runtime-api.ts) استفاده کنید - هرگز Plugin خودتان را از طریق مسیر SDK آن import نکنید.

    برای Pluginهای ارائه‌دهنده، helperهای مخصوص ارائه‌دهنده را در همان barrelهای ریشهٔ package نگه دارید، مگر اینکه seam واقعاً عمومی باشد. نمونه‌های bundled فعلی:

    • Anthropic: wrapperهای stream Claude و helperهای service_tier / beta
    • OpenAI: builderهای ارائه‌دهنده، helperهای مدل پیش‌فرض، ارائه‌دهنده‌های realtime
    • OpenRouter: builder ارائه‌دهنده به‌همراه helperهای onboarding/config

    اگر یک helper فقط داخل یک package ارائه‌دهندهٔ bundled مفید است، آن را به‌جای ارتقا به openclaw/plugin-sdk/* روی همان seam ریشهٔ package نگه دارید.

    برخی seamهای helper تولیدشدهٔ openclaw/plugin-sdk/<bundled-id> هنوز برای نگهداری bundled-Pluginها، وقتی استفادهٔ owner رهگیری‌شده دارند، وجود دارند. با آن‌ها به‌عنوان سطوح رزرو‌شده رفتار کنید، نه الگوی پیش‌فرض برای Pluginهای جدید شخص ثالث.

    چک‌لیست پیش از ارسال

    OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s package.json فرادادهٔ درست openclaw را دارد OPENCLAW_DOCS_MARKER:calloutClose:

    OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s manifest openclaw.plugin.json موجود و معتبر است OPENCLAW_DOCS_MARKER:calloutClose:

    OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s نقطهٔ ورود از defineChannelPluginEntry یا definePluginEntry استفاده می‌کند OPENCLAW_DOCS_MARKER:calloutClose:

    OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s همهٔ importها از مسیرهای متمرکز plugin-sdk/<subpath> استفاده می‌کنند OPENCLAW_DOCS_MARKER:calloutClose:

    Was this useful?