---
read_when:
    - ساخت یا اشکال‌زدایی Pluginهای بومی OpenClaw
    - درک مدل قابلیت‌های Plugin یا مرزهای مالکیت
    - کار روی خط لولهٔ بارگذاری Plugin یا رجیستری
    - پیاده‌سازی هوک‌های زمان اجرای ارائه‌دهنده یا Pluginهای کانال
sidebarTitle: Internals
summary: 'جزئیات داخلی Plugin: مدل قابلیت، مالکیت، قراردادها، خط لوله بارگذاری و ابزارهای کمکی زمان اجرا'
title: جزئیات داخلی Plugin
x-i18n:
    generated_at: "2026-07-12T10:25:32Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    provider: openai
    source_hash: 07ab077080285b5b7a93f58f71cd00be62cfd79cdc2cfa40f0e64cc91cc5ac46
    source_path: plugins/architecture.md
    workflow: 16
---

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

<CardGroup cols={2}>
  <Card title="نصب و استفاده از Pluginها" icon="plug" href="/fa/tools/plugin">
    راهنمای کاربر نهایی برای افزودن، فعال‌سازی و عیب‌یابی Pluginها.
  </Card>
  <Card title="ساخت Pluginها" icon="rocket" href="/fa/plugins/building-plugins">
    آموزش ساخت نخستین Plugin با کوچک‌ترین مانیفست قابل‌استفاده.
  </Card>
  <Card title="Pluginهای کانال" icon="comments" href="/fa/plugins/sdk-channel-plugins">
    یک Plugin کانال پیام‌رسانی بسازید.
  </Card>
  <Card title="Pluginهای ارائه‌دهنده" icon="microchip" href="/fa/plugins/sdk-provider-plugins">
    یک Plugin ارائه‌دهنده مدل بسازید.
  </Card>
  <Card title="نمای کلی SDK" icon="book" href="/fa/plugins/sdk-overview">
    مرجع نگاشت واردسازی و API ثبت.
  </Card>
</CardGroup>

## مدل عمومی قابلیت‌ها

قابلیت‌ها، مدل عمومی **Plugin بومی** درون OpenClaw هستند. هر Plugin بومی OpenClaw برای یک یا چند نوع قابلیت ثبت می‌شود:

| قابلیت                     | روش ثبت                                           | نمونه Pluginها                    |
| -------------------------- | ------------------------------------------------ | --------------------------------- |
| استنتاج متنی               | `api.registerProvider(...)`                      | `anthropic`, `openai`             |
| بک‌اند استنتاج CLI         | `api.registerCliBackend(...)`                    | `anthropic`, `openai`             |
| تعبیه‌سازی‌ها              | `api.registerEmbeddingProvider(...)`             | Pluginهای برداری متعلق به ارائه‌دهنده |
| گفتار                      | `api.registerSpeechProvider(...)`                | `elevenlabs`, `microsoft`         |
| رونویسی بلادرنگ            | `api.registerRealtimeTranscriptionProvider(...)` | `openai`                          |
| صدای بلادرنگ               | `api.registerRealtimeVoiceProvider(...)`         | `google`, `openai`                |
| درک رسانه                  | `api.registerMediaUnderstandingProvider(...)`    | `google`, `openai`                |
| منبع رونویسی‌ها            | `api.registerTranscriptSourceProvider(...)`      | `discord`                         |
| تولید تصویر                | `api.registerImageGenerationProvider(...)`       | `fal`, `google`, `openai`         |
| تولید موسیقی               | `api.registerMusicGenerationProvider(...)`       | `fal`, `google`, `minimax`        |
| تولید ویدئو                | `api.registerVideoGenerationProvider(...)`       | `fal`, `google`, `qwen`           |
| دریافت از وب               | `api.registerWebFetchProvider(...)`              | `firecrawl`                       |
| جست‌وجوی وب                | `api.registerWebSearchProvider(...)`             | `brave`, `firecrawl`, `google`    |
| کانال / پیام‌رسانی         | `api.registerChannel(...)`                       | `matrix`, `msteams`               |
| کشف Gateway                | `api.registerGatewayDiscoveryService(...)`       | `bonjour`                         |

<Note>
Pluginی که هیچ قابلیتی ثبت نمی‌کند، اما قلاب‌ها، ابزارها، سرویس‌های کشف یا سرویس‌های پس‌زمینه ارائه می‌دهد، یک Plugin **قدیمیِ صرفاً قلابی** است. این الگو همچنان به‌طور کامل پشتیبانی می‌شود.
</Note>

### رویکرد سازگاری خارجی

مدل قابلیت‌ها اکنون در هسته پیاده‌سازی شده و امروزه Pluginهای همراه/بومی از آن استفاده می‌کنند، اما سازگاری Pluginهای خارجی هنوز به معیار سخت‌گیرانه‌تری از «صادر شده است، پس ثابت شده است» نیاز دارد.

| وضعیت Plugin                                       | راهنمایی                                                                                                          |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Pluginهای خارجی موجود                            | یکپارچه‌سازی‌های مبتنی بر قلاب را فعال نگه دارید؛ این خط مبنای سازگاری است.                                      |
| Pluginهای همراه/بومی جدید                        | ثبت صریح قابلیت را بر دسترسی‌های ویژه فروشنده یا طراحی‌های جدیدِ صرفاً قلابی ترجیح دهید.                         |
| Pluginهای خارجی که ثبت قابلیت را می‌پذیرند       | مجاز است، اما سطوح کمکی مختص قابلیت را در حال تکامل در نظر بگیرید، مگر اینکه مستندات آن‌ها را پایدار اعلام کنند. |

ثبت قابلیت، مسیر موردنظر است. در دوره گذار، قلاب‌های قدیمی همچنان امن‌ترین مسیر بدون شکست برای Pluginهای خارجی هستند. همه زیرمسیرهای کمکی صادرشده یکسان نیستند — قراردادهای محدود و مستند را بر صادرات کمکی اتفاقی ترجیح دهید.

### شکل‌های Plugin

OpenClaw هر Plugin بارگذاری‌شده را بر اساس رفتار واقعی ثبت آن، نه صرفاً فراداده ایستا، در یکی از شکل‌ها طبقه‌بندی می‌کند:

<AccordionGroup>
  <Accordion title="قابلیت ساده">
    دقیقاً یک نوع قابلیت ثبت می‌کند؛ برای مثال، یک Plugin صرفاً ارائه‌دهنده مانند `arcee` یا `chutes`.
  </Accordion>
  <Accordion title="قابلیت ترکیبی">
    چند نوع قابلیت ثبت می‌کند؛ برای مثال، `openai` مالک استنتاج متنی، گفتار، درک رسانه و تولید تصویر است.
  </Accordion>
  <Accordion title="صرفاً قلابی">
    فقط قلاب‌ها را ثبت می‌کند، چه نوع‌دار و چه سفارشی، و هیچ قابلیت، ابزار، فرمان یا سرویسی ثبت نمی‌کند.
  </Accordion>
  <Accordion title="فاقد قابلیت">
    ابزارها، فرمان‌ها، سرویس‌ها یا مسیرها را ثبت می‌کند، اما هیچ قابلیتی ثبت نمی‌کند.
  </Accordion>
</AccordionGroup>

برای مشاهده شکل و تفکیک قابلیت‌های یک Plugin، از `openclaw plugins inspect <id>` استفاده کنید. برای جزئیات به [مرجع CLI](/fa/cli/plugins#inspect) مراجعه کنید.

### قلاب‌های قدیمی

قلاب `before_agent_start` همچنان به‌عنوان مسیر سازگاری برای Pluginهای صرفاً قلابی پشتیبانی می‌شود. Pluginهای قدیمیِ واقعی هنوز به آن وابسته‌اند.

مسیر پیش‌رو:

- فعال نگه داشتن آن
- مستندسازی آن به‌عنوان قابلیت قدیمی
- ترجیح `before_model_resolve` برای کارهای بازنویسی مدل/ارائه‌دهنده
- ترجیح `before_prompt_build` برای کارهای تغییر اعلان
- حذف آن تنها پس از کاهش استفاده واقعی و اثبات ایمنی مهاجرت توسط پوشش نمونه‌های آزمایشی

### نشانه‌های سازگاری

`openclaw doctor`، `openclaw plugins inspect <id>`، `openclaw status --all` و `openclaw plugins doctor` این اعلان‌های سازگاری را نمایش می‌دهند:

| نشانه                                      | معنا                                                                                                                    |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| **پیکربندی معتبر**                         | پیکربندی بدون مشکل تجزیه می‌شود و Pluginها با موفقیت تفکیک می‌شوند                                                    |
| **صرفاً قلابی** (اطلاعات)                  | Plugin فقط قلاب ثبت می‌کند؛ مسیری پشتیبانی‌شده است، اما هنوز به ثبت قابلیت مهاجرت نکرده است                             |
| **`before_agent_start` قدیمی** (هشدار)     | Plugin به‌جای `before_model_resolve`/`before_prompt_build` از قلاب منسوخ‌شده `before_agent_start` استفاده می‌کند       |
| **API منسوخ تعبیه‌سازی حافظه** (هشدار)     | Plugin غیرهمراه به‌جای `registerEmbeddingProvider` از API قدیمی ارائه‌دهنده تعبیه‌سازی مختص حافظه استفاده می‌کند       |
| **خطای قطعی**                              | پیکربندی نامعتبر است یا بارگذاری Plugin ناموفق بوده است                                                                 |

هیچ‌یک از نشانه‌های توصیه‌ای/هشداردهنده امروز موجب ازکارافتادن Plugin شما نمی‌شوند. این نشانه‌ها در `openclaw status --all` و `openclaw plugins doctor` نیز ظاهر می‌شوند.

## نمای کلی معماری

سیستم Plugin در OpenClaw چهار لایه دارد:

<Steps>
  <Step title="مانیفست و کشف">
    OpenClaw، Pluginهای نامزد را در مسیرهای پیکربندی‌شده، ریشه‌های فضای کاری، ریشه‌های سراسری Plugin و Pluginهای همراه پیدا می‌کند. فرایند کشف ابتدا مانیفست‌های بومی `openclaw.plugin.json` و سپس مانیفست‌های بسته پشتیبانی‌شده را می‌خواند.
  </Step>
  <Step title="فعال‌سازی و اعتبارسنجی">
    هسته تعیین می‌کند که یک Plugin کشف‌شده فعال، غیرفعال، مسدود یا برای یک جایگاه انحصاری مانند حافظه انتخاب شده است.
  </Step>
  <Step title="بارگذاری زمان اجرا">
    Pluginهای بومی OpenClaw درون همان فرایند بارگذاری می‌شوند و قابلیت‌ها را در یک رجیستری مرکزی ثبت می‌کنند. JavaScript بسته‌بندی‌شده از طریق `require` بومی بارگذاری می‌شود؛ TypeScript منبع محلی شخص ثالث، راهکار اضطراری Jiti است. بسته‌های سازگار بدون واردکردن کد زمان اجرا به رکوردهای رجیستری نرمال‌سازی می‌شوند.
  </Step>
  <Step title="مصرف سطح‌ها">
    بخش‌های دیگر OpenClaw رجیستری را می‌خوانند تا ابزارها، کانال‌ها، راه‌اندازی ارائه‌دهنده، قلاب‌ها، مسیرهای HTTP، فرمان‌های CLI و سرویس‌ها را در دسترس قرار دهند.
  </Step>
</Steps>

به‌طور مشخص برای CLI مربوط به Plugin، کشف فرمان ریشه در دو مرحله تقسیم می‌شود:

- فراداده زمان تجزیه از `registerCli(..., { descriptors: [...] })` می‌آید
- ماژول واقعی CLI مربوط به Plugin می‌تواند تنبل باقی بماند و در نخستین فراخوانی ثبت شود

این کار کد CLI متعلق به Plugin را درون همان Plugin نگه می‌دارد و در عین حال به OpenClaw اجازه می‌دهد نام فرمان‌های ریشه را پیش از تجزیه رزرو کند.

مرز طراحی مهم:

- اعتبارسنجی مانیفست/پیکربندی باید بدون اجرای کد Plugin و بر اساس **فراداده مانیفست/شِما** کار کند
- کشف قابلیت بومی ممکن است کد ورودی Plugin مورداعتماد را برای ساخت یک تصویر لحظه‌ای غیرفعال از رجیستری بارگذاری کند
- رفتار بومی زمان اجرا از مسیر `register(api)` در ماژول Plugin با `api.registrationMode === "full"` می‌آید

این جداسازی به OpenClaw امکان می‌دهد پیش از فعال‌شدن کامل زمان اجرا، پیکربندی را اعتبارسنجی کند، Pluginهای مفقود/غیرفعال را توضیح دهد و راهنمایی‌های رابط کاربری/شِما را بسازد.

### تصویر لحظه‌ای فراداده Plugin و جدول جست‌وجو

در شروع Gateway، یک `PluginMetadataSnapshot` برای تصویر لحظه‌ای فعلی پیکربندی ساخته می‌شود. این تصویر لحظه‌ای فقط شامل فراداده است: نمایه Pluginهای نصب‌شده، رجیستری مانیفست، اطلاعات تشخیصی مانیفست، نگاشت‌های مالک، نرمال‌ساز شناسه Plugin و رکوردهای مانیفست را ذخیره می‌کند. ماژول‌های بارگذاری‌شده Plugin، SDKهای ارائه‌دهنده، محتوای بسته‌ها یا خروجی‌های زمان اجرا را نگه نمی‌دارد.

اعتبارسنجی پیکربندی آگاه از Plugin، فعال‌سازی خودکار هنگام راه‌اندازی و راه‌اندازی اولیه Pluginهای Gateway به‌جای بازسازی مستقل فراداده مانیفست/نمایه، از این تصویر لحظه‌ای استفاده می‌کنند. `PluginLookUpTable` از همان تصویر لحظه‌ای مشتق می‌شود و برنامه Pluginهای آغازین را برای پیکربندی فعلی زمان اجرا به آن می‌افزاید.

پس از راه‌اندازی، Gateway تصویر لحظه‌ای فعلی فراداده را به‌عنوان یک محصول قابل‌جایگزینی زمان اجرا نگه می‌دارد. کشف مکرر ارائه‌دهنده در زمان اجرا می‌تواند به‌جای بازسازی نمایه نصب‌شده و رجیستری مانیفست برای هر گذر فهرست ارائه‌دهنده، آن تصویر لحظه‌ای را قرض بگیرد. این تصویر لحظه‌ای هنگام خاموش‌شدن Gateway، تغییر پیکربندی/موجودی Plugin و نوشتن نمایه نصب‌شده پاک یا جایگزین می‌شود؛ اگر تصویر لحظه‌ای جاری و سازگاری وجود نداشته باشد، فراخوان‌ها به مسیر سرد مانیفست/نمایه بازمی‌گردند. بررسی‌های سازگاری باید ریشه‌های کشف Plugin مانند `plugins.load.paths` و فضای کاری پیش‌فرض عامل را دربر گیرند، زیرا Pluginهای فضای کاری بخشی از دامنه فراداده هستند.

تصویر لحظه‌ای و جدول جست‌وجو، تصمیم‌های تکراری هنگام راه‌اندازی را در مسیر سریع نگه می‌دارند:

- مالکیت کانال
- راه‌اندازی به‌تعویق‌افتاده کانال
- شناسه‌های Plugin هنگام راه‌اندازی
- مالکیت ارائه‌دهنده و بک‌اند CLI
- مالکیت ارائه‌دهنده راه‌اندازی، نام مستعار فرمان، ارائه‌دهنده فهرست مدل و قرارداد مانیفست
- اعتبارسنجی شِمای پیکربندی Plugin و شِمای پیکربندی کانال
- تصمیم‌های فعال‌سازی خودکار هنگام راه‌اندازی

مرز ایمنی، جایگزینی تصویر لحظه‌ای است، نه تغییر آن. هنگامی که پیکربندی، موجودی Plugin، رکوردهای نصب یا سیاست پایدار نمایه تغییر می‌کند، تصویر لحظه‌ای را دوباره بسازید. آن را یک رجیستری سراسری، گسترده و تغییرپذیر در نظر نگیرید و تاریخچه نامحدودی از تصویرهای لحظه‌ای نگه ندارید. بارگذاری Plugin در زمان اجرا از تصویرهای لحظه‌ای فراداده جدا باقی می‌ماند تا وضعیت کهنه زمان اجرا پشت یک حافظه نهان فراداده پنهان نشود.

قاعده حافظه نهان در [جزئیات داخلی معماری Plugin](/fa/plugins/architecture-internals#plugin-cache-boundary) مستند شده است: فراداده مانیفست و کشف تازه هستند، مگر اینکه فراخواننده یک تصویر لحظه‌ای صریح، جدول جست‌وجو یا رجیستری مانیفست را برای جریان فعلی نگه دارد. حافظه‌های نهان پنهان فراداده و TTLهای مبتنی بر ساعت دیواری بخشی از بارگذاری Plugin نیستند. فقط حافظه‌های نهان بارگذار زمان اجرا، ماژول و مصنوعات وابستگی می‌توانند پس از بارگذاری واقعی کد یا مصنوعات نصب‌شده پایدار بمانند.

برخی فراخواننده‌های مسیر سرد همچنان رجیستری‌های مانیفست را مستقیماً از نمایه پایدار Pluginهای نصب‌شده بازسازی می‌کنند، به‌جای اینکه یک `PluginLookUpTable` از Gateway دریافت کنند. این مسیر اکنون رجیستری را هنگام نیاز بازسازی می‌کند؛ وقتی فراخواننده از قبل یکی از آن‌ها را دارد، عبور دادن جدول جست‌وجوی فعلی یا یک رجیستری مانیفست صریح از میان جریان‌های زمان اجرا را ترجیح دهید.

### برنامه‌ریزی فعال‌سازی

برنامه‌ریزی فعال‌سازی بخشی از صفحه کنترل است. فراخوانندگان می‌توانند پیش از بارگذاری رجیستری‌های گسترده‌تر زمان اجرا، بپرسند کدام Pluginها برای یک فرمان، ارائه‌دهنده، کانال، مسیر، چارچوب عامل یا قابلیت مشخص مرتبط هستند.

برنامه‌ریز، سازگاری رفتار فعلی مانیفست را حفظ می‌کند:

- فیلدهای `activation.*` راهنمای صریح برنامه‌ریز هستند
- `providers`، `channels`، `commandAliases`، `setup.providers`، `contracts.tools` و هوک‌ها همچنان سازوکار جایگزین مالکیت مانیفست باقی می‌مانند
- API برنامه‌ریزِ فقط‌شناسه‌ها برای فراخوانندگان موجود همچنان در دسترس است
- API طرح، برچسب‌های دلیل را گزارش می‌کند تا ابزارهای تشخیصی بتوانند راهنمایی‌های صریح را از سازوکار جایگزین مالکیت تشخیص دهند

<Warning>
`activation` را هوک چرخه‌عمر یا جایگزینی برای `register(...)` تلقی نکنید. این فراداده برای محدودکردن بارگذاری استفاده می‌شود. هنگامی که فیلدهای مالکیت از قبل رابطه را توصیف می‌کنند، آن‌ها را ترجیح دهید؛ از `activation` فقط برای راهنمایی‌های تکمیلی برنامه‌ریز استفاده کنید.
</Warning>

### Pluginهای کانال و ابزار پیام مشترک

Pluginهای کانال برای کنش‌های عادی گفت‌وگو نیازی به ثبت ابزار جداگانه‌ای برای ارسال، ویرایش یا واکنش ندارند. OpenClaw یک ابزار مشترک `message` را در هسته نگه می‌دارد و Pluginهای کانال مالک کشف و اجرای مختص کانال در پشت آن هستند.

مرز فعلی چنین است:

- هسته مالک میزبان ابزار مشترک `message`، سیم‌کشی پرامپت، ثبت و مدیریت نشست/رشته و توزیع اجرا است
- Pluginهای کانال مالک کشف کنش محدودشده، کشف قابلیت و هر قطعه طرح‌واره مختص کانال هستند
- Pluginهای کانال مالک دستور زبان مکالمه نشستِ مختص ارائه‌دهنده هستند؛ مانند نحوه کدگذاری شناسه‌های رشته در شناسه‌های مکالمه یا ارث‌بری آن‌ها از مکالمات والد
- Pluginهای کانال کنش نهایی را از طریق آداپتور کنش خود اجرا می‌کنند

برای Pluginهای کانال، سطح SDK برابر `ChannelMessageActionAdapter.describeMessageTool(...)` است. این فراخوانی یکپارچه کشف به Plugin اجازه می‌دهد کنش‌های قابل‌مشاهده، قابلیت‌ها و مشارکت‌های طرح‌واره خود را با هم بازگرداند تا این بخش‌ها از یکدیگر منحرف نشوند.

هنگامی که پارامتر مختص کانالِ ابزار پیام، منبع رسانه‌ای مانند مسیر محلی یا URL رسانه راه دور را حمل می‌کند، Plugin باید `mediaSourceParams` را نیز از `describeMessageTool(...)` بازگرداند. هسته از این فهرست صریح برای اعمال نرمال‌سازی مسیر جعبه‌شنی و راهنمایی‌های دسترسی رسانه خروجی استفاده می‌کند، بدون آنکه نام پارامترهای متعلق به Plugin را به‌صورت ثابت در کد قرار دهد. در این بخش، نگاشت‌های محدود به کنش را به یک فهرست تختِ سراسری برای کانال ترجیح دهید تا یک پارامتر رسانه‌ای مخصوص پروفایل روی کنش‌های نامرتبطی مانند `send` نرمال‌سازی نشود.

هسته دامنه زمان اجرا را به آن مرحله کشف منتقل می‌کند. فیلدهای مهم عبارت‌اند از:

- `accountId`
- `currentChannelId`
- `currentThreadTs`
- `currentMessageId`
- `sessionKey`
- `sessionId`
- `agentId`
- `requesterSenderId` ورودیِ مورداعتماد

این موضوع برای Pluginهای حساس به زمینه اهمیت دارد. یک کانال می‌تواند بر اساس حساب فعال، اتاق/رشته/پیام فعلی یا هویت درخواست‌کننده مورداعتماد، کنش‌های پیام را پنهان یا آشکار کند، بدون آنکه شاخه‌های مختص کانال در ابزار هسته‌ای `message` به‌صورت ثابت در کد قرار گیرند.

به همین دلیل، تغییرات مسیریابی اجراکننده تعبیه‌شده همچنان کار Plugin محسوب می‌شوند: اجراکننده مسئول انتقال هویت گفت‌وگو/نشست فعلی به مرز کشف Plugin است تا ابزار مشترک `message` سطح متعلق به کانالِ مناسب را برای نوبت فعلی ارائه کند.

برای ابزارهای کمکی اجرای متعلق به کانال، Pluginهای همراه باید زمان اجرای اجرا را درون ماژول‌های Plugin خود نگه دارند. هسته دیگر مالک زمان اجراهای کنش پیام Discord، Slack، Telegram یا WhatsApp در `src/agents/tools` نیست. زیرمسیرهای جداگانه `plugin-sdk/*-action-runtime` را منتشر نمی‌کنیم و Pluginهای همراه باید کد زمان اجرای محلی خود را مستقیماً از ماژول‌های متعلق به Plugin خود وارد کنند.

همین مرز به‌طور کلی درباره درزهای SDK با نام ارائه‌دهنده نیز صدق می‌کند: هسته نباید بسته‌های تجمیعی تسهیل‌کننده مختص کانال را برای Discord، Signal، Slack، WhatsApp یا Pluginهای مشابه وارد کند. اگر هسته به رفتاری نیاز دارد، باید بسته تجمیعی `api.ts` / `runtime-api.ts` خودِ Plugin همراه را مصرف کند یا آن نیاز را به یک قابلیت عمومی محدود در SDK مشترک ارتقا دهد.

Pluginهای همراه از همین قاعده پیروی می‌کنند. `runtime-api.ts` یک Plugin همراه نباید نمای برندشده `openclaw/plugin-sdk/<plugin-id>` خود را دوباره صادر کند. آن نماهای برندشده به‌عنوان لایه‌های سازگاری برای Pluginهای خارجی و مصرف‌کنندگان قدیمی‌تر باقی می‌مانند، اما Pluginهای همراه باید از صادرات محلی به‌همراه زیرمسیرهای عمومی محدود SDK مانند `openclaw/plugin-sdk/channel-policy`، `openclaw/plugin-sdk/runtime-store` یا `openclaw/plugin-sdk/webhook-ingress` استفاده کنند. کد جدید نباید نماهای SDK مختص شناسه Plugin اضافه کند، مگر آنکه مرز سازگاری یک زیست‌بوم خارجی موجود به آن نیاز داشته باشد.

به‌طور خاص برای نظرسنجی‌ها، دو مسیر اجرا وجود دارد:

- `outbound.sendPoll` خط پایه مشترک برای کانال‌هایی است که با مدل عمومی نظرسنجی سازگارند
- `actions.handleAction("poll")` مسیر ترجیحی برای معناشناسی مختص کانالِ نظرسنجی یا پارامترهای اضافی نظرسنجی است

هسته اکنون تجزیه مشترک نظرسنجی را تا پس از آنکه توزیع نظرسنجی Plugin کنش را رد کند به تعویق می‌اندازد؛ بنابراین مدیریت‌کننده‌های نظرسنجی متعلق به Plugin می‌توانند فیلدهای نظرسنجی مختص کانال را بپذیرند، بدون آنکه ابتدا تجزیه‌گر عمومی نظرسنجی مانع آن‌ها شود.

برای مشاهده توالی کامل راه‌اندازی، به [جزئیات داخلی معماری Plugin](/fa/plugins/architecture-internals) مراجعه کنید.

## مدل مالکیت قابلیت

OpenClaw یک Plugin بومی را مرز مالکیت یک **شرکت** یا یک **ویژگی** در نظر می‌گیرد، نه مجموعه‌ای درهم از یکپارچه‌سازی‌های نامرتبط.

یعنی:

- یک Plugin شرکتی معمولاً باید مالک تمام سطوح رو‌به‌OpenClaw آن شرکت باشد
- یک Plugin ویژگی معمولاً باید مالک کل سطح ویژگی‌ای باشد که معرفی می‌کند
- کانال‌ها باید به‌جای پیاده‌سازی مجدد و موردی رفتار ارائه‌دهنده، قابلیت‌های مشترک هسته را مصرف کنند

<AccordionGroup>
  <Accordion title="فروشنده چندقابلیتی">
    `google` مالک استنتاج متن، پشتیبان CLI، جاسازی‌ها، گفتار، صدای بلادرنگ، درک رسانه، تولید تصویر/موسیقی/ویدئو و جست‌وجوی وب است. `openai` مالک استنتاج متن، جاسازی‌ها، گفتار، رونویسی بلادرنگ، صدای بلادرنگ، درک رسانه و تولید تصویر/ویدئو است. `minimax` مالک استنتاج متن به‌همراه درک رسانه، گفتار، تولید تصویر/موسیقی/ویدئو و جست‌وجوی وب است.
  </Accordion>
  <Accordion title="فروشنده تک‌قابلیتی">
    `arcee` و `chutes` فقط مالک استنتاج متن هستند؛ `microsoft` فقط مالک گفتار است. یک Plugin فروشنده می‌تواند تا زمانی که نیاز به پوشش بخش بیشتری از سطح آن فروشنده نداشته باشد، در همین حد محدود باقی بماند.
  </Accordion>
  <Accordion title="Plugin ویژگی">
    `voice-call` مالک انتقال تماس، ابزارها، CLI، مسیرها و پل‌زنی جریان رسانه Twilio است، اما به‌جای واردکردن مستقیم Pluginهای فروشنده، قابلیت‌های مشترک گفتار، رونویسی بلادرنگ و صدای بلادرنگ را مصرف می‌کند.
  </Accordion>
</AccordionGroup>

وضعیت نهایی موردنظر چنین است:

- سطح رو‌به‌OpenClaw یک فروشنده، حتی اگر مدل‌های متنی، گفتار، تصاویر و ویدئو را دربر گیرد، در یک Plugin قرار می‌گیرد
- فروشندگان دیگر نیز می‌توانند همین کار را برای محدوده سطح خود انجام دهند
- کانال‌ها اهمیتی نمی‌دهند کدام Plugin فروشنده مالک ارائه‌دهنده است؛ آن‌ها قرارداد قابلیت مشترکی را مصرف می‌کنند که هسته ارائه می‌دهد

تمایز کلیدی چنین است:

- **Plugin** = مرز مالکیت
- **قابلیت** = قرارداد هسته که چندین Plugin می‌توانند آن را پیاده‌سازی یا مصرف کنند

بنابراین اگر OpenClaw دامنه جدیدی مانند ویدئو اضافه کند، پرسش نخست این نیست که «کدام ارائه‌دهنده باید مدیریت ویدئو را به‌صورت ثابت در کد قرار دهد؟» پرسش نخست این است که «قرارداد قابلیت ویدئوی هسته چیست؟» پس از ایجاد آن قرارداد، Pluginهای فروشنده می‌توانند در برابر آن ثبت شوند و Pluginهای کانال/ویژگی می‌توانند آن را مصرف کنند.

اگر قابلیت هنوز وجود ندارد، معمولاً اقدام درست چنین است:

<Steps>
  <Step title="تعریف قابلیت">
    قابلیت مفقود را در هسته تعریف کنید.
  </Step>
  <Step title="ارائه از طریق SDK">
    آن را به‌شکلی نوع‌دار از طریق API/زمان اجرای Plugin ارائه کنید.
  </Step>
  <Step title="سیم‌کشی مصرف‌کنندگان">
    کانال‌ها/ویژگی‌ها را به آن قابلیت متصل کنید.
  </Step>
  <Step title="پیاده‌سازی‌های فروشنده">
    اجازه دهید Pluginهای فروشنده پیاده‌سازی‌ها را ثبت کنند.
  </Step>
</Steps>

این رویکرد، ضمن جلوگیری از رفتار هسته‌ای وابسته به یک فروشنده واحد یا مسیر کد اختصاصی و یک‌باره برای یک Plugin، مالکیت را صریح نگه می‌دارد.

### لایه‌بندی قابلیت

هنگام تصمیم‌گیری درباره محل قرارگیری کد، از این مدل ذهنی استفاده کنید:

<Tabs>
  <Tab title="لایه قابلیت هسته">
    هماهنگ‌سازی مشترک، خط‌مشی، سازوکار جایگزین، قواعد ادغام پیکربندی، معناشناسی تحویل و قراردادهای نوع‌دار.
  </Tab>
  <Tab title="لایه Plugin فروشنده">
    APIهای مختص فروشنده، احراز هویت، کاتالوگ‌های مدل، سنتز گفتار، تولید تصویر، پشتیبان‌های ویدئو و نقاط پایانی مصرف.
  </Tab>
  <Tab title="لایه Plugin کانال/ویژگی">
    یکپارچه‌سازی Discord/Slack/voice-call/و موارد مشابه که قابلیت‌های هسته را مصرف و آن‌ها را روی یک سطح ارائه می‌کند.
  </Tab>
</Tabs>

برای نمونه، TTS از این ساختار پیروی می‌کند:

- هسته مالک خط‌مشی TTS هنگام پاسخ، ترتیب سازوکارهای جایگزین، ترجیحات و تحویل کانال است
- `elevenlabs`، `google`، `microsoft` و `openai` مالک پیاده‌سازی‌های سنتز هستند
- `voice-call` ابزار کمکی زمان اجرای TTS تلفنی را مصرف می‌کند

همین الگو باید برای قابلیت‌های آینده ترجیح داده شود.

### نمونه Plugin شرکتی چندقابلیتی

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

```ts
import type { OpenClawPluginDefinition } from "openclaw/plugin-sdk/plugin-entry";
import {
  describeImageWithModel,
  transcribeOpenAiCompatibleAudio,
} from "openclaw/plugin-sdk/media-understanding";
import { createPluginBackedWebSearchProvider } from "openclaw/plugin-sdk/provider-web-search";

const plugin: OpenClawPluginDefinition = {
  id: "exampleai",
  name: "ExampleAI",
  register(api) {
    api.registerProvider({
      id: "exampleai",
      // auth/model catalog/runtime hooks
    });

    api.registerSpeechProvider({
      id: "exampleai",
      // vendor speech config — implement the SpeechProviderPlugin interface directly
    });

    api.registerMediaUnderstandingProvider({
      id: "exampleai",
      capabilities: ["image", "audio", "video"],
      async describeImage(req) {
        return describeImageWithModel({
          ...req,
          provider: "exampleai",
        });
      },
      async transcribeAudio(req) {
        return transcribeOpenAiCompatibleAudio({
          ...req,
          provider: "exampleai",
        });
      },
    });

    api.registerWebSearchProvider(
      createPluginBackedWebSearchProvider({
        id: "exampleai-search",
        // credential + fetch logic
      }),
    );
  },
};

export default plugin;
```

آنچه اهمیت دارد نام دقیق ابزارهای کمکی نیست؛ ساختار مهم است:

- یک Plugin مالک سطح فروشنده است
- هسته همچنان مالک قراردادهای قابلیت است
- کانال‌ها و Pluginهای ویژگی، ابزارهای کمکی `api.runtime.*` را مصرف می‌کنند، نه کد فروشنده را
- آزمون‌های قرارداد می‌توانند تأیید کنند که Plugin قابلیت‌هایی را که ادعای مالکیتشان را دارد ثبت کرده است

### نمونه قابلیت: درک ویدئو

OpenClaw از قبل درک تصویر/صدا/ویدئو را یک قابلیت مشترک در نظر می‌گیرد. همان مدل مالکیت در اینجا نیز اعمال می‌شود:

<Steps>
  <Step title="هسته قرارداد را تعریف می‌کند">
    هسته قرارداد درک رسانه را تعریف می‌کند.
  </Step>
  <Step title="Pluginهای فروشنده ثبت می‌شوند">
    Pluginهای فروشنده، حسب مورد، `describeImage`، `transcribeAudio` و `describeVideo` را ثبت می‌کنند.
  </Step>
  <Step title="مصرف‌کنندگان از رفتار مشترک استفاده می‌کنند">
    کانال‌ها و Pluginهای ویژگی به‌جای اتصال مستقیم به کد فروشنده، رفتار مشترک هسته را مصرف می‌کنند.
  </Step>
</Steps>

این کار از جای‌دادن فرضیات ویدئویی یک ارائه‌دهنده در هسته جلوگیری می‌کند. Plugin مالک سطح فروشنده است؛ هسته مالک قرارداد قابلیت و رفتار جایگزین است.

تولید ویدئو نیز از همین توالی استفاده می‌کند: هسته مالک قرارداد قابلیت نوع‌دار و ابزار کمکی زمان اجرا است و Pluginهای فروشنده پیاده‌سازی‌های `api.registerVideoGenerationProvider(...)` را در برابر آن ثبت می‌کنند.

به فهرست بررسی اجرایی مشخصی نیاز دارید؟ به [راهنمای عملی قابلیت](/fa/plugins/adding-capabilities) مراجعه کنید.

## قراردادها و اعمال آن‌ها

سطح API مربوط به Plugin عمداً به‌صورت نوع‌دار و متمرکز در `OpenClawPluginApi` تعریف شده است. این قرارداد، نقاط ثبت پشتیبانی‌شده و کمک‌تابع‌های زمان اجرایی را که یک Plugin می‌تواند به آن‌ها متکی باشد، مشخص می‌کند.

دلیل اهمیت این موضوع:

- نویسندگان Plugin از یک استاندارد داخلی پایدار برخوردار می‌شوند
- هسته می‌تواند مالکیت تکراری را رد کند؛ برای مثال، ثبت شناسه یکسان ارائه‌دهنده توسط دو Plugin
- هنگام راه‌اندازی می‌توان عیب‌یابی‌های قابل‌اقدام برای ثبت‌های نادرست ارائه کرد
- آزمون‌های قرارداد می‌توانند مالکیت Pluginهای همراه را اعمال کنند و از انحراف بی‌سروصدا جلوگیری کنند

اعمال این قواعد در دو لایه انجام می‌شود:

<AccordionGroup>
  <Accordion title="اعمال ثبت در زمان اجرا">
    رجیستری Plugin هنگام بارگذاری Pluginها، ثبت‌ها را اعتبارسنجی می‌کند. برای نمونه، شناسه‌های تکراری ارائه‌دهنده، شناسه‌های تکراری ارائه‌دهنده گفتار و ثبت‌های نادرست، به‌جای رفتار تعریف‌نشده، عیب‌یابی‌های Plugin ایجاد می‌کنند.
  </Accordion>
  <Accordion title="آزمون‌های قرارداد">
    Pluginهای همراه هنگام اجرای آزمون در رجیستری‌های قرارداد ثبت می‌شوند تا OpenClaw بتواند مالکیت را صریحاً بررسی کند. در حال حاضر، این سازوکار برای ارائه‌دهندگان مدل، ارائه‌دهندگان گفتار، ارائه‌دهندگان جست‌وجوی وب و مالکیت ثبت‌های همراه استفاده می‌شود.
  </Accordion>
</AccordionGroup>

اثر عملی این است که OpenClaw از ابتدا می‌داند کدام Plugin مالک کدام سطح است. این امر به هسته و کانال‌ها امکان می‌دهد بدون اصطکاک با یکدیگر ترکیب شوند، زیرا مالکیت به‌جای ضمنی بودن، اعلام‌شده، نوع‌دار و آزمون‌پذیر است.

### چه چیزی باید در یک قرارداد باشد

<Tabs>
  <Tab title="قراردادهای مناسب">
    - نوع‌دار
    - کوچک
    - مختص قابلیت
    - تحت مالکیت هسته
    - قابل‌استفاده مجدد توسط چند Plugin
    - قابل‌مصرف توسط کانال‌ها/ویژگی‌ها بدون نیاز به شناخت فروشنده

  </Tab>
  <Tab title="قراردادهای نامناسب">
    - خط‌مشی مختص فروشنده که در هسته پنهان شده است
    - راه‌های فرار موردی Plugin که رجیستری را دور می‌زنند
    - دسترسی مستقیم کد کانال به پیاده‌سازی یک فروشنده
    - اشیای موردی زمان اجرا که بخشی از `OpenClawPluginApi` یا `api.runtime` نیستند

  </Tab>
</Tabs>

در صورت تردید، سطح انتزاع را بالاتر ببرید: ابتدا قابلیت را تعریف کنید، سپس اجازه دهید Pluginها به آن متصل شوند.

## مدل اجرا

Pluginهای بومی OpenClaw به‌صورت **درون‌فرایندی** همراه با Gateway اجرا می‌شوند. آن‌ها در محیط ایزوله اجرا نمی‌شوند. یک Plugin بومی بارگذاری‌شده همان مرز اعتماد در سطح فرایند را دارد که کد هسته دارد.

<Warning>
پیامدهای Plugin بومی: یک Plugin می‌تواند ابزارها، کنترل‌کننده‌های شبکه، هوک‌ها و سرویس‌ها را ثبت کند؛ یک اشکال در Plugin می‌تواند Gateway را از کار بیندازد یا ناپایدار کند؛ و یک Plugin بومی مخرب معادل اجرای کد دلخواه درون فرایند OpenClaw است.
</Warning>

بسته‌های سازگار به‌طور پیش‌فرض امن‌ترند، زیرا OpenClaw در حال حاضر با آن‌ها به‌عنوان بسته‌های فراداده/محتوا رفتار می‌کند. در نسخه‌های فعلی، این موضوع عمدتاً به Skills همراه اشاره دارد.

برای Pluginهای غیرهمراه از فهرست‌های مجاز و مسیرهای صریح نصب/بارگذاری استفاده کنید. با Pluginهای فضای کاری به‌عنوان کد زمان توسعه رفتار کنید، نه پیش‌فرض‌های محیط عملیاتی.

برای نام بسته‌های همراه فضای کاری، شناسه Plugin را به نام npm متصل نگه دارید: به‌طور پیش‌فرض `@openclaw/<id>`، یا هنگامی که بسته عمداً نقش محدودتری برای Plugin ارائه می‌کند، از پسوند نوع‌دار تأییدشده‌ای مانند `-provider`، `-plugin`، `-speech`، `-sandbox` یا `-media-understanding` استفاده کنید.

<Note>
**نکته اعتماد:** `plugins.allow` به **شناسه‌های Plugin** اعتماد می‌کند، نه به منشأ منبع. یک Plugin فضای کاری با شناسه یکسان با یک Plugin همراه، هنگامی که فعال یا در فهرست مجاز قرار گرفته باشد، عمداً نسخه همراه را تحت‌الشعاع قرار می‌دهد. این رفتار عادی است و برای توسعه محلی، آزمودن وصله‌ها و اصلاحات فوری مفید است. اعتماد به Plugin همراه از روی تصویر لحظه‌ای منبع — مانیفست و کد موجود روی دیسک در زمان بارگذاری — تعیین می‌شود، نه از روی فراداده نصب. یک رکورد نصب خراب یا جایگزین‌شده نمی‌تواند بی‌سروصدا سطح اعتماد یک Plugin همراه را فراتر از ادعاهای منبع واقعی گسترش دهد.
</Note>

## مرز صدور

OpenClaw قابلیت‌ها را صادر می‌کند، نه تسهیلات پیاده‌سازی را.

ثبت قابلیت را عمومی نگه دارید. صدور کمک‌تابع‌های خارج از قرارداد را محدود کنید:

- زیرمسیرهای کمک‌تابع مختص Pluginهای همراه
- زیرمسیرهای زیرساخت زمان اجرا که قرار نیست API عمومی باشند
- کمک‌تابع‌های تسهیل‌کننده مختص فروشنده
- کمک‌تابع‌های راه‌اندازی/آغازبه‌کار که جزئیات پیاده‌سازی هستند

زیرمسیرهای رزروشده کمک‌تابع Pluginهای همراه از نگاشت صدور SDK تولیدشده کنار گذاشته شده‌اند. کمک‌تابع‌های مختص مالک را درون بسته Plugin مالک نگه دارید؛ فقط رفتار قابل‌استفاده مجدد میزبان را به قراردادهای عمومی SDK مانند `plugin-sdk/gateway-runtime`، `plugin-sdk/security-runtime` و `plugin-sdk/plugin-config-runtime` ارتقا دهید.

## جزئیات داخلی و مرجع

برای خط لوله بارگذاری، مدل رجیستری، هوک‌های زمان اجرای ارائه‌دهنده، مسیرهای HTTP مربوط به Gateway، طرح‌واره‌های ابزار پیام، تفکیک مقصد کانال، کاتالوگ‌های ارائه‌دهنده، Pluginهای موتور زمینه و راهنمای افزودن یک قابلیت جدید، به [جزئیات داخلی معماری Plugin](/fa/plugins/architecture-internals) مراجعه کنید.

## مرتبط

- [ساخت Pluginها](/fa/plugins/building-plugins)
- [مانیفست Plugin](/fa/plugins/manifest)
- [راه‌اندازی SDK مربوط به Plugin](/fa/plugins/sdk-setup)
