Внутрішні механізми Plugin
Це поглиблений довідник з архітектури. Практичні посібники дивіться тут:
- Установлення та використання плагінів — посібник користувача
- Початок роботи — перший навчальний посібник зі створення плагіна
- Plugin каналів — створення каналу обміну повідомленнями
- Plugin провайдерів — створення провайдера моделей
- Огляд SDK — карта імпортів і API реєстрації
Публічна модель можливостей
Можливості — це публічна модель власних Plugin у межах OpenClaw. Кожен власний Plugin OpenClaw реєструється для одного або кількох типів можливостей:| Можливість | Метод реєстрації | Приклади Plugin |
|---|---|---|
| Текстовий інференс | api.registerProvider(...) | openai, anthropic |
| Backend інференсу 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.registerMusicGenerationProvider(...) | google, minimax |
| Генерація відео | api.registerVideoGenerationProvider(...) | qwen |
| Отримання вебданих | api.registerWebFetchProvider(...) | firecrawl |
| Вебпошук | api.registerWebSearchProvider(...) | google |
| Канал / обмін повідомленнями | api.registerChannel(...) | msteams, matrix |
Позиція щодо зовнішньої сумісності
Модель можливостей уже реалізована в core і сьогодні використовується вбудованими/власними Plugin, але сумісність із зовнішніми Plugin усе ще потребує вищої планки, ніж «це експортується, отже це незмінний контракт». Поточні рекомендації:- наявні зовнішні Plugin: зберігайте працездатність інтеграцій на основі хуків; вважайте це базовим рівнем сумісності
- нові вбудовані/власні Plugin: надавайте перевагу явній реєстрації можливостей замість vendor-specific звернень углиб системи або нових реалізацій лише з хуками
- зовнішні Plugin, що переходять на реєстрацію можливостей: це дозволено, але вважайте допоміжні поверхні для конкретних можливостей такими, що еволюціонують, якщо в документації контракт явно не позначено як стабільний
- API реєстрації можливостей — це цільовий напрямок
- застарілі хуки залишаються найбезпечнішим шляхом без ризику поломок для зовнішніх Plugin під час переходу
- не всі експортовані допоміжні підшляхи однакові; надавайте перевагу вузькому задокументованому контракту, а не випадковим допоміжним експортам
Форми Plugin
OpenClaw класифікує кожен завантажений Plugin за формою на основі його фактичної поведінки реєстрації, а не лише статичних метаданих:- plain-capability — реєструє рівно один тип можливості (наприклад,
Plugin лише провайдера, як-от
mistral) - hybrid-capability — реєструє кілька типів можливостей (наприклад,
openaiволодіє текстовим інференсом, мовленням, розумінням медіа та генерацією зображень) - hook-only — реєструє лише хуки (типізовані або власні), без можливостей, інструментів, команд чи сервісів
- non-capability — реєструє інструменти, команди, сервіси або маршрути, але не можливості
openclaw plugins inspect <id>, щоб побачити форму Plugin і
розподіл можливостей. Докладніше дивіться в довіднику CLI.
Застарілі хуки
Хукbefore_agent_start залишається підтримуваним шляхом сумісності для
Plugin лише з хуками. Від нього все ще залежать реальні застарілі Plugin.
Напрямок:
- зберігати його працездатність
- документувати його як застарілий
- для роботи з перевизначенням моделі/провайдера надавати перевагу
before_model_resolve - для модифікації prompt надавати перевагу
before_prompt_build - вилучати лише після зменшення реального використання і підтвердження безпечності міграції покриттям фікстур
Сигнали сумісності
Коли ви запускаєтеopenclaw doctor або openclaw plugins inspect <id>, ви
можете побачити одну з таких міток:
| Сигнал | Значення |
|---|---|
| config valid | Конфігурація коректно розбирається, а Plugin успішно визначаються |
| compatibility advisory | Plugin використовує підтримуваний, але старіший шаблон (наприклад, hook-only) |
| legacy warning | Plugin використовує before_agent_start, який застарів |
| hard error | Конфігурація недійсна або Plugin не вдалося завантажити |
hook-only, ні before_agent_start сьогодні не зламають ваш Plugin —
hook-only є рекомендаційним сигналом, а before_agent_start лише спричиняє
попередження. Ці сигнали також відображаються в openclaw status --all і
openclaw plugins doctor.
Огляд архітектури
Система Plugin в OpenClaw має чотири шари:- Маніфест + виявлення
OpenClaw знаходить кандидатів у Plugin у налаштованих шляхах, коренях
робочих просторів, глобальних коренях розширень і вбудованих розширеннях.
Під час виявлення спочатку зчитуються власні маніфести
openclaw.plugin.jsonразом із підтримуваними маніфестами пакетів. - Увімкнення + валідація Core вирішує, чи є знайдений Plugin увімкненим, вимкненим, заблокованим або вибраним для ексклюзивного слота, наприклад пам’яті.
- Завантаження часу виконання Власні Plugin OpenClaw завантажуються в межах процесу через jiti і реєструють можливості в центральному реєстрі. Сумісні пакети нормалізуються в записи реєстру без імпорту коду часу виконання.
- Використання поверхонь Решта OpenClaw читає реєстр, щоб надавати інструменти, канали, налаштування провайдерів, хуки, HTTP-маршрути, команди CLI та сервіси.
- метадані під час розбору надходять із
registerCli(..., { descriptors: [...] }) - фактичний модуль CLI Plugin може залишатися лінивим і реєструватися лише під час першого виклику
- виявлення + валідація конфігурації мають працювати на основі метаданих маніфесту/схеми без виконання коду Plugin
- власна поведінка часу виконання надходить із шляху
register(api)модуля Plugin
Plugin каналів і спільний інструмент повідомлень
Plugin каналів не потрібно реєструвати окремий інструмент send/edit/react для звичайних дій чату. OpenClaw зберігає один спільний інструментmessage у core,
а Plugin каналів володіють специфічним для каналу виявленням і виконанням за ним.
Поточна межа така:
- core володіє хостом спільного інструмента
message, підключенням до prompt, веденням сесій/гілок і диспетчеризацією виконання - Plugin каналів володіють виявленням дій у межах області, виявленням можливостей і будь-якими фрагментами схеми, специфічними для каналу
- Plugin каналів володіють граматикою розмови сесії, специфічною для провайдера, наприклад тим, як ідентифікатори розмов кодують ідентифікатори гілок або успадковуються від батьківських розмов
- Plugin каналів виконують фінальну дію через свій адаптер дій
ChannelMessageActionAdapter.describeMessageTool(...). Цей уніфікований виклик
виявлення дозволяє Plugin повертати видимі дії, можливості та внески в схему
разом, щоб ці частини не розходилися.
Коли параметр інструмента повідомлень, специфічний для каналу, містить джерело
медіа, наприклад локальний шлях або віддалений URL медіа, Plugin також має
повертати mediaSourceParams з describeMessageTool(...). Core використовує
цей явний список, щоб застосовувати нормалізацію шляхів sandbox і підказки
щодо вихідного доступу до медіа без жорсткого кодування імен параметрів,
які належать Plugin.
Там слід надавати перевагу maps з областю дії на рівні дій, а не одному
плоскому списку для всього каналу, щоб параметр медіа лише для профілю не
нормалізувався для не пов’язаних дій, таких як send.
Core передає область часу виконання в цей крок виявлення. Важливі поля містять:
accountIdcurrentChannelIdcurrentThreadTscurrentMessageIdsessionKeysessionIdagentId- довірений вхідний
requesterSenderId
message.
Саме тому зміни маршрутизації embedded-runner усе ще належать до роботи Plugin:
runner відповідає за передавання поточної ідентичності чату/сесії в межу
виявлення Plugin, щоб спільний інструмент message відкривав правильну
поверхню, яка належить каналу, для поточного ходу.
Для допоміжних засобів виконання, які належать каналу, вбудовані Plugin мають
зберігати runtime виконання у власних модулях розширень. Core більше не
володіє runtime дій повідомлень Discord, Slack, Telegram або WhatsApp у
src/agents/tools. Ми не публікуємо окремі підшляхи plugin-sdk/*-action-runtime,
а вбудовані Plugin мають імпортувати свій локальний runtime-код напряму з
модулів, що належать їхнім розширенням.
Така сама межа застосовується і до SDK-швів, названих на честь провайдерів, загалом:
core не має імпортувати зручні barrels, специфічні для каналів Slack, Discord,
Signal, WhatsApp або подібних розширень. Якщо core потрібна певна поведінка,
слід або використати власний barrel api.ts / runtime-api.ts вбудованого Plugin,
або підняти цю потребу до вузької узагальненої можливості в спільному SDK.
Зокрема для опитувань є два шляхи виконання:
outbound.sendPoll— спільна базова реалізація для каналів, що відповідають загальній моделі опитуваньactions.handleAction("poll")— бажаний шлях для специфічної для каналу семантики опитувань або додаткових параметрів опитування
Модель володіння можливостями
OpenClaw розглядає власний Plugin як межу володіння для компанії або функції, а не як набір не пов’язаних інтеграцій. Це означає:- Plugin компанії зазвичай має володіти всіма поверхнями OpenClaw, що належать цій компанії
- Plugin функції зазвичай має володіти повною поверхнею функції, яку він додає
- канали мають споживати спільні можливості core замість того, щоб довільно повторно реалізовувати поведінку провайдерів
- вбудований Plugin
openaiволодіє поведінкою провайдера моделей OpenAI і поведінкою OpenAI для мовлення + голосу в реальному часі + розуміння медіа + генерації зображень - вбудований Plugin
elevenlabsволодіє поведінкою мовлення ElevenLabs - вбудований Plugin
microsoftволодіє поведінкою мовлення Microsoft - вбудований Plugin
googleволодіє поведінкою провайдера моделей Google, а також поведінкою Google для розуміння медіа + генерації зображень + вебпошуку - вбудований Plugin
firecrawlволодіє поведінкою Firecrawl для отримання вебданих - вбудовані Plugin
minimax,mistral,moonshotіzaiволодіють своїми backends розуміння медіа - вбудований Plugin
qwenволодіє поведінкою текстового провайдера Qwen, а також поведінкою для розуміння медіа і генерації відео - Plugin
voice-callє Plugin функції: він володіє транспортом викликів, інструментами, CLI, маршрутами та мостом медіапотоку Twilio, але споживає спільні можливості мовлення, а також транскрибування в реальному часі й голосу в реальному часі замість прямого імпорту vendor Plugin
- OpenAI живе в одному Plugin, навіть якщо він охоплює текстові моделі, мовлення, зображення та майбутнє відео
- інший vendor може зробити те саме для власної області поверхонь
- канали не повинні зважати на те, який vendor Plugin володіє провайдером; вони споживають спільний контракт можливостей, який надає core
- plugin = межа володіння
- capability = контракт core, який можуть реалізовувати або споживати кілька Plugin
- визначити відсутню можливість у core
- відкрити її через API/runtime Plugin у типізований спосіб
- під’єднати канали/функції до цієї можливості
- дозволити vendor Plugin реєструвати реалізації
Шарування можливостей
Користуйтеся цією ментальною моделлю, коли вирішуєте, де має бути код:- шар можливостей core: спільна оркестрація, політика, fallback, правила злиття конфігурації, семантика доставки та типізовані контракти
- шар vendor Plugin: API, автентифікація, каталоги моделей, синтез мовлення, генерація зображень, майбутні backends відео, endpoints використання, специфічні для vendor
- шар Plugin каналу/функції: інтеграція Slack/Discord/voice-call тощо, яка споживає можливості core і подає їх на певну поверхню
- core володіє політикою TTS під час відповіді, порядком fallback, налаштуваннями та доставкою в канал
openai,elevenlabsіmicrosoftволодіють реалізаціями синтезуvoice-callспоживає допоміжний runtime засіб TTS для телефонії
Приклад Plugin компанії з кількома можливостями
Plugin компанії має виглядати цілісно ззовні. Якщо OpenClaw має спільні контракти для моделей, мовлення, транскрибування в реальному часі, голосу в реальному часі, розуміння медіа, генерації зображень, генерації відео, отримання вебданих і вебпошуку, vendor може володіти всіма своїми поверхнями в одному місці:- один Plugin володіє поверхнею vendor
- core, як і раніше, володіє контрактами можливостей
- Plugin каналів і функцій споживають допоміжні засоби
api.runtime.*, а не код vendor - тести контрактів можуть перевіряти, що Plugin зареєстрував можливості, якими він заявляє, що володіє
Приклад можливості: розуміння відео
OpenClaw уже розглядає розуміння зображень/аудіо/відео як одну спільну можливість. Тут застосовується та сама модель володіння:- core визначає контракт розуміння медіа
- vendor Plugin реєструють
describeImage,transcribeAudioіdescribeVideo, де це застосовно - Plugin каналів і функцій споживають спільну поведінку core замість прямого підключення до коду vendor
api.registerVideoGenerationProvider(...) для цього контракту.
Потрібен конкретний контрольний список розгортання? Дивіться
Capability Cookbook.
Контракти та примусове забезпечення
Поверхня API Plugin навмисно типізована й централізована вOpenClawPluginApi. Цей контракт визначає підтримувані точки реєстрації та
допоміжні runtime-засоби, на які може покладатися Plugin.
Чому це важливо:
- автори Plugin отримують єдиний стабільний внутрішній стандарт
- core може відхиляти дубльоване володіння, наприклад коли два Plugin реєструють один і той самий id провайдера
- під час запуску можна показувати діагностику з конкретними порадами для неправильної реєстрації
- тести контрактів можуть забезпечувати володіння вбудованих Plugin і запобігати тихому дрейфу
- забезпечення під час runtime-реєстрації Реєстр Plugin перевіряє реєстрації під час завантаження Plugin. Наприклад: дубльовані id провайдерів, дубльовані id провайдерів мовлення та неправильно сформовані реєстрації призводять до діагностики Plugin, а не до невизначеної поведінки.
- тести контрактів Вбудовані Plugin фіксуються в реєстрах контрактів під час виконання тестів, щоб OpenClaw міг явно перевіряти володіння. Сьогодні це використовується для провайдерів моделей, провайдерів мовлення, провайдерів вебпошуку та володіння реєстрацією вбудованих Plugin.
Що має входити до контракту
Хороші контракти Plugin:- типізовані
- невеликі
- специфічні для можливості
- належать core
- придатні для повторного використання кількома Plugin
- можуть споживатися каналами/функціями без знання про vendor
- політика, специфічна для vendor, прихована в core
- одноразові обхідні шляхи Plugin, які оминають реєстр
- код каналу, що напряму звертається до реалізації vendor
- ad hoc runtime-об’єкти, які не є частиною
OpenClawPluginApiабоapi.runtime
Модель виконання
Власні Plugin OpenClaw виконуються в межах процесу разом із Gateway. Вони не ізольовані sandbox-середовищем. Завантажений власний Plugin має ту саму межу довіри на рівні процесу, що й код core. Наслідки:- власний Plugin може реєструвати інструменти, мережеві обробники, хуки та сервіси
- помилка власного Plugin може аварійно завершити роботу gateway або дестабілізувати його
- зловмисний власний Plugin еквівалентний довільному виконанню коду всередині процесу OpenClaw
@openclaw/<id> за замовчуванням або схвалений типізований суфікс, наприклад
-provider, -plugin, -speech, -sandbox або -media-understanding, якщо
пакет навмисно відкриває вужчу роль Plugin.
Важлива примітка щодо довіри:
plugins.allowдовіряє id Plugin, а не походженню джерела.- Plugin робочого простору з тим самим id, що й у вбудованого Plugin, навмисно затіняє вбудовану копію, коли такий Plugin робочого простору ввімкнено/додано до allowlist.
- Це нормально й корисно для локальної розробки, тестування патчів і hotfix-ів.
Межа експортів
OpenClaw експортує можливості, а не зручні реалізації. Зберігайте публічною реєстрацію можливостей. Прибирайте експорти допоміжних засобів, які не є контрактами:- підшляхи допоміжних засобів, специфічні для вбудованих Plugin
- підшляхи runtime-проводки, не призначені як публічний API
- зручні допоміжні засоби, специфічні для vendor
- допоміжні засоби setup/onboarding, що є деталями реалізації
plugin-sdk/feishu, plugin-sdk/feishu-setup, plugin-sdk/zalo,
plugin-sdk/zalo-setup і кілька швів plugin-sdk/matrix*. Розглядайте їх як
зарезервовані експорти деталей реалізації, а не як рекомендований шаблон SDK для
нових сторонніх Plugin.
Конвеєр завантаження
Під час запуску OpenClaw приблизно виконує таке:- виявляє корені кандидатів для Plugin
- зчитує власні маніфести або маніфести сумісних пакетів і метадані пакетів
- відхиляє небезпечних кандидатів
- нормалізує конфігурацію Plugin (
plugins.enabled,allow,deny,entries,slots,load.paths) - вирішує стан увімкнення для кожного кандидата
- завантажує увімкнені власні модулі через jiti
- викликає власні хуки
register(api)(абоactivate(api)— застарілий псевдонім) і збирає реєстрації в реєстр Plugin - відкриває реєстр для поверхонь команд/runtime
activate — це застарілий псевдонім для register — завантажувач визначає, що саме є (def.register ?? def.activate), і викликає це в тій самій точці. Усі вбудовані Plugin використовують register; для нових Plugin надавайте перевагу register.Поведінка manifest-first
Маніфест — це джерело істини для control plane. OpenClaw використовує його, щоб:- ідентифікувати Plugin
- виявляти задекларовані канали/Skills/схему конфігурації або можливості пакета
- валідувати
plugins.entries.<id>.config - доповнювати мітки/placeholder-значення Control UI
- показувати метадані встановлення/каталогу
- зберігати дешеві дескриптори активації та setup без завантаження runtime Plugin
activation і setup залишаються в control plane.
Це лише дескриптори метаданих для планування активації та виявлення setup;
вони не замінюють runtime-реєстрацію, register(...) або setupEntry.
Перші активні споживачі активації тепер використовують підказки маніфесту щодо команд, каналів і провайдерів,
щоб звузити завантаження Plugin до ширшої матеріалізації реєстру:
- завантаження CLI звужується до Plugin, які володіють запитаною основною командою
- визначення setup/Plugin каналу звужується до Plugin, які володіють запитаним id каналу
- явне визначення setup/runtime провайдера звужується до Plugin, які володіють запитаним id провайдера
setup.providers і
setup.cliBackends, щоб звузити коло кандидатів Plugin, перш ніж повертатися до
setup-api для Plugin, яким усе ще потрібні runtime-хуки на етапі setup. Якщо більше
ніж один виявлений Plugin заявляє про один і той самий нормалізований id провайдера setup
або backend CLI, пошук setup відмовляється від неоднозначного власника замість того, щоб
покладатися на порядок виявлення.
Що кешує завантажувач
OpenClaw зберігає короткоживучі кеші в межах процесу для:- результатів виявлення
- даних реєстру маніфестів
- завантажених реєстрів Plugin
- Установіть
OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1абоOPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1, щоб вимкнути ці кеші. - Налаштовуйте вікна кешу через
OPENCLAW_PLUGIN_DISCOVERY_CACHE_MSіOPENCLAW_PLUGIN_MANIFEST_CACHE_MS.
Модель реєстру
Завантажені Plugin не змінюють безпосередньо довільні глобальні об’єкти core. Вони реєструються в центральному реєстрі Plugin. Реєстр відстежує:- записи Plugin (ідентичність, джерело, походження, статус, діагностика)
- інструменти
- застарілі хуки й типізовані хуки
- канали
- провайдери
- обробники Gateway RPC
- HTTP-маршрути
- реєстратори CLI
- фонові сервіси
- команди, що належать Plugin
- модуль Plugin -> реєстрація в реєстрі
- runtime core -> споживання реєстру
Зворотні виклики прив’язування розмови
Plugin, які прив’язують розмову, можуть реагувати, коли схвалення завершено. Використовуйтеapi.onConversationBindingResolved(...), щоб отримати зворотний виклик після того,
як запит на прив’язування буде схвалено або відхилено:
status:"approved"або"denied"decision:"allow-once","allow-always"або"deny"binding: узгоджене прив’язування для схвалених запитівrequest: початковий зведений запит, підказка від’єднання, id відправника та метадані розмови
Runtime-хуки провайдера
Plugin провайдерів тепер мають два шари:- метадані маніфесту:
providerAuthEnvVarsдля дешевого пошуку env-auth провайдера до завантаження runtime,providerAuthAliasesдля варіантів провайдера, які спільно використовують auth,channelEnvVarsдля дешевого пошуку env/setup каналу до завантаження runtime, а такожproviderAuthChoicesдля дешевих міток onboarding/auth-choice і метаданих прапорців CLI до завантаження runtime - хуки часу конфігурації:
catalog/ застарілийdiscoveryплюсapplyConfigDefaults - runtime-хуки:
normalizeModelId,normalizeTransport,normalizeConfig,applyNativeStreamingUsageCompat,resolveConfigApiKey,resolveSyntheticAuth,resolveExternalAuthProfiles,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, коли провайдер має облікові дані на основі env,
які мають бачити узагальнені шляхи auth/status/model-picker без завантаження runtime Plugin.
Використовуйте маніфест providerAuthAliases, коли один id провайдера має повторно
використовувати env vars, auth profiles, auth на основі конфігурації та варіант onboarding choice для API-ключа
іншого id провайдера. Використовуйте маніфест providerAuthChoices, коли поверхні CLI для onboarding/auth-choice
мають знати choice id провайдера, мітки груп і просту auth-проводку з одним прапорцем
без завантаження runtime провайдера. Зберігайте runtime envVars провайдера для операторських підказок,
таких як мітки onboarding або setup vars для OAuth client-id/client-secret.
Використовуйте маніфест channelEnvVars, коли канал має auth або setup на основі env, які
мають бачити узагальнений shell-env fallback, перевірки config/status або підказки setup
без завантаження runtime каналу.
Порядок хуків і використання
Для Plugin моделей/провайдерів OpenClaw викликає хуки приблизно в такому порядку. Стовпець «Коли використовувати» — це короткий посібник для ухвалення рішень.| # | Хук | Що він робить | Коли використовувати |
|---|---|---|---|
| 1 | catalog | Публікує конфігурацію провайдера в models.providers під час генерації models.json | Провайдер володіє каталогом або базовими значеннями base URL |
| 2 | applyConfigDefaults | Застосовує глобальні значення конфігурації за замовчуванням, які належать провайдеру, під час матеріалізації конфігурації | Значення за замовчуванням залежать від режиму auth, env або семантики сімейства моделей провайдера |
| — | (вбудований пошук моделі) | OpenClaw спочатку пробує звичайний шлях через реєстр/каталог | (це не хук Plugin) |
| 3 | normalizeModelId | Нормалізує застарілі або preview-псевдоніми id моделей перед пошуком | Провайдер володіє очищенням псевдонімів до канонічного визначення моделі |
| 4 | normalizeTransport | Нормалізує api / baseUrl сімейства провайдера перед узагальненим складанням моделі | Провайдер володіє очищенням транспорту для власних id провайдера в межах того самого сімейства транспорту |
| 5 | normalizeConfig | Нормалізує models.providers.<id> до визначення runtime/провайдера | Провайдеру потрібне очищення конфігурації, яке має жити разом із Plugin; допоміжні засоби вбудованого сімейства Google також страхують підтримувані записи конфігурації Google |
| 6 | applyNativeStreamingUsageCompat | Застосовує compat-переписування native streaming usage до конфігурації провайдерів | Провайдеру потрібні виправлення метаданих native streaming usage, що залежать від endpoint |
| 7 | resolveConfigApiKey | Визначає auth на основі env-marker для конфігураційних провайдерів до завантаження runtime auth | Провайдер має власне визначення API-ключа через env-marker; amazon-bedrock також має тут вбудований resolver AWS env-marker |
| 8 | resolveSyntheticAuth | Виводить локальний/self-hosted або auth на основі конфігурації без збереження відкритого тексту | Провайдер може працювати із synthetic/local маркером облікових даних |
| 9 | resolveExternalAuthProfiles | Накладає зовнішні профілі auth, що належать провайдеру; типове значення persistence — runtime-only для облікових даних, що належать CLI/app | Провайдер повторно використовує зовнішні облікові дані auth без збереження скопійованих refresh token |
| 10 | shouldDeferSyntheticProfileAuth | Понижує пріоритет збережених synthetic placeholder-профілів порівняно з auth на основі env/config | Провайдер зберігає synthetic placeholder-профілі, які не повинні мати вищий пріоритет |
| 11 | resolveDynamicModel | Синхронний fallback для id моделей, що належать провайдеру, але ще відсутні в локальному реєстрі | Провайдер приймає довільні id моделей від upstream |
| 12 | prepareDynamicModel | Асинхронний прогрів, після чого resolveDynamicModel запускається знову | Провайдеру потрібні мережеві метадані до визначення невідомих id |
| 13 | normalizeResolvedModel | Остаточне переписування перед тим, як embedded runner використає визначену модель | Провайдеру потрібні переписування транспорту, але при цьому він усе ще використовує транспорт core |
| 14 | contributeResolvedModelCompat | Додає compat-прапорці для моделей vendor за іншим сумісним транспортом | Провайдер розпізнає власні моделі на proxy-транспортах, не перебираючи на себе провайдера |
| 15 | capabilities | Метадані транскрипту/інструментів, що належать провайдеру, і використовуються спільною логікою core | Провайдеру потрібні особливості транскрипту/сімейства провайдера |
| 16 | normalizeToolSchemas | Нормалізує схеми інструментів до того, як їх побачить embedded runner | Провайдеру потрібне очищення схем для сімейства транспорту |
| 17 | inspectToolSchemas | Показує діагностику схем, що належить провайдеру, після нормалізації | Провайдер хоче мати попередження щодо ключових слів без навчання core правилам, специфічним для провайдера |
| 18 | resolveReasoningOutputMode | Вибирає native чи tagged-контракт виводу reasoning | Провайдеру потрібен tagged reasoning/final output замість native-полів |
| 19 | prepareExtraParams | Нормалізація параметрів запиту до застосування узагальнених обгорток параметрів потоку | Провайдеру потрібні параметри запиту за замовчуванням або очищення параметрів для конкретного провайдера |
| 20 | createStreamFn | Повністю замінює звичайний шлях потоку власним транспортом | Провайдеру потрібен власний wire protocol, а не просто обгортка |
| 21 | wrapStreamFn | Обгортка потоку після застосування узагальнених обгорток | Провайдеру потрібні обгортки сумісності заголовків/тіла/моделі запиту без власного транспорту |
| 22 | resolveTransportTurnState | Прикріплює native-заголовки транспорту або метадані для кожного ходу | Провайдер хоче, щоб узагальнені транспорти надсилали native-ідентичність ходу провайдера |
| 23 | resolveWebSocketSessionPolicy | Прикріплює native-заголовки WebSocket або політику cooling-down сесії | Провайдер хоче, щоб узагальнені WS-транспорти налаштовували заголовки сесії або політику fallback |
| 24 | formatApiKey | Форматер профілю auth: збережений профіль стає runtime-рядком apiKey | Провайдер зберігає додаткові метадані auth і потребує власної форми runtime-токена |
| 25 | refreshOAuth | Перевизначення оновлення OAuth для власних endpoint оновлення або політики помилки оновлення | Провайдер не відповідає спільним refreshers pi-ai |
| 26 | buildAuthDoctorHint | Підказка виправлення, що додається, коли оновлення OAuth не вдається | Провайдеру потрібна власна порада з відновлення auth після помилки оновлення |
| 27 | matchesContextOverflowError | Matcher переповнення контекстного вікна, що належить провайдеру | Провайдер має сирі помилки переповнення, які узагальнені евристики пропустили б |
| 28 | classifyFailoverReason | Класифікація причини failover, що належить провайдеру | Провайдер може зіставляти сирі API/транспортні помилки з rate-limit, overload тощо |
| 29 | isCacheTtlEligible | Політика prompt-cache для proxy/backhaul-провайдерів | Провайдеру потрібне керування TTL кешу, специфічне для proxy |
| 30 | buildMissingAuthMessage | Замінник узагальненого повідомлення відновлення за відсутності auth | Провайдеру потрібна власна підказка відновлення за відсутності auth |
| 31 | suppressBuiltInModel | Приховування застарілих upstream-моделей плюс необов’язкова підказка про помилку для користувача | Провайдеру потрібно приховати застарілі upstream-рядки або замінити їх підказкою від vendor |
| 32 | augmentModelCatalog | Synthetic/остаточні рядки каталогу, додані після виявлення | Провайдеру потрібні synthetic-рядки прямої сумісності в models list і вибирачах |
| 33 | isBinaryThinking | Перемикач reasoning увімк./вимк. для провайдерів із binary-thinking | Провайдер відкриває лише binary thinking on/off |
| 34 | supportsXHighThinking | Підтримка reasoning xhigh для вибраних моделей | Провайдер хоче xhigh лише для підмножини моделей |
| 35 | resolveDefaultThinkingLevel | Типовий рівень /think для конкретного сімейства моделей | Провайдер володіє типовою політикою /think для сімейства моделей |
| 36 | isModernModelRef | Matcher сучасної моделі для фільтрів live profile і вибору smoke | Провайдер володіє зіставленням preferred-model для live/smoke |
| 37 | prepareRuntimeAuth | Обмінює налаштовані облікові дані на фактичний runtime-токен/ключ безпосередньо перед інференсом | Провайдеру потрібен обмін токена або короткоживучі облікові дані запиту |
| 38 | resolveUsageAuth | Визначає облікові дані usage/billing для /usage і пов’язаних поверхонь статусу | Провайдеру потрібен власний парсер токенів usage/quota або інші облікові дані для usage |
| 39 | fetchUsageSnapshot | Отримує та нормалізує знімки usage/quota, специфічні для провайдера, після визначення auth | Провайдеру потрібен endpoint usage, специфічний для провайдера, або парсер корисного навантаження |
| 40 | createEmbeddingProvider | Створює адаптер embedding, що належить провайдеру, для пам’яті/пошуку | Поведінка memory embedding має належати Plugin провайдера |
| 41 | buildReplayPolicy | Повертає політику replay, яка керує обробкою транскриптів для провайдера | Провайдеру потрібна власна політика транскриптів (наприклад, видалення блоків thinking) |
| 42 | sanitizeReplayHistory | Переписує історію replay після узагальненого очищення транскрипту | Провайдеру потрібні власні переписування replay, специфічні для провайдера, понад спільні допоміжні засоби Compaction |
| 43 | validateReplayTurns | Остаточна валідація або переформатування ходів replay перед embedded runner | Транспорту провайдера потрібна суворіша валідація ходів після узагальненої санітизації |
| 44 | onModelSelected | Запускає побічні ефекти після вибору моделі, що належать провайдеру | Провайдеру потрібна телеметрія або стан, що належить провайдеру, коли модель стає активною |
normalizeModelId, normalizeTransport і normalizeConfig спочатку перевіряють
відповідний Plugin провайдера, а потім переходять до інших Plugin провайдерів, здатних обробляти хуки,
доки один із них справді не змінить id моделі або transport/config. Це зберігає
працездатність shim-рішень alias/compat для провайдерів без вимоги, щоб викликач знав,
який саме вбудований Plugin володіє переписуванням. Якщо жоден хук провайдера не переписує
підтримуваний запис конфігурації сімейства Google, нормалізатор конфігурації вбудованого Google
усе одно застосовує це сумісне очищення.
Якщо провайдеру потрібен повністю власний wire protocol або власний виконавець запитів,
це вже інший клас розширення. Ці хуки призначені для поведінки провайдера, яка все ще
виконується в межах звичайного циклу інференсу OpenClaw.
Приклад провайдера
Вбудовані приклади
- Anthropic використовує
resolveDynamicModel,capabilities,buildAuthDoctorHint,resolveUsageAuth,fetchUsageSnapshot,isCacheTtlEligible,resolveDefaultThinkingLevel,applyConfigDefaults,isModernModelRefіwrapStreamFn, оскільки він володіє прямою сумісністю з Claude 4.6, підказками сімейства провайдера, вказівками з відновлення auth, інтеграцією з endpoint usage, придатністю prompt-cache, значеннями конфігурації за замовчуванням, що враховують auth, типовою/адаптивною політикою thinking для Claude і формуванням потоку, специфічним для Anthropic, для beta headers,/fast/serviceTierтаcontext1m. - Допоміжні засоби потоку Anthropic, специфічні для Claude, поки що залишаються у
власному публічному шві
api.ts/contract-api.tsвбудованого Plugin. Ця поверхня пакета експортуєwrapAnthropicProviderStream,resolveAnthropicBetas,resolveAnthropicFastMode,resolveAnthropicServiceTierі низькорівневі засоби побудови обгорток Anthropic замість розширення узагальненого SDK навколо правил beta headers одного провайдера. - OpenAI використовує
resolveDynamicModel,normalizeResolvedModelіcapabilities, а такожbuildMissingAuthMessage,suppressBuiltInModel,augmentModelCatalog,supportsXHighThinkingіisModernModelRef, оскільки він володіє прямою сумісністю з GPT-5.4, прямою нормалізацією OpenAIopenai-completions->openai-responses, підказками auth з урахуванням Codex, приглушенням Spark, synthetic-рядками списку OpenAI та політикою thinking / live-model для GPT-5; сімейство потоківopenai-responses-defaultsволодіє спільними native-обгортками OpenAI Responses для attribution headers,/fast/serviceTier, багатослівності тексту, native вебпошуку Codex, формуванням корисного навантаження reasoning-compat і керуванням контекстом Responses. - OpenRouter використовує
catalogразом ізresolveDynamicModelіprepareDynamicModel, оскільки провайдер є наскрізним і може відкривати нові id моделей раніше, ніж оновиться статичний каталог OpenClaw; він також використовуєcapabilities,wrapStreamFnіisCacheTtlEligible, щоб заголовки запитів, метадані маршрутизації, патчі reasoning і політика prompt-cache, специфічні для провайдера, не потрапляли в core. Його політика replay надходить із сімействаpassthrough-gemini, тоді як сімейство потоківopenrouter-thinkingволодіє ін’єкцією reasoning через proxy і пропусками для непідтримуваних моделей /auto. - GitHub Copilot використовує
catalog,auth,resolveDynamicModelіcapabilities, а такожprepareRuntimeAuthіfetchUsageSnapshot, оскільки йому потрібні вхід через пристрій, що належить провайдеру, поведінка fallback моделей, особливості транскриптів Claude, обмін GitHub token -> Copilot token і endpoint usage, що належить провайдеру. - OpenAI Codex використовує
catalog,resolveDynamicModel,normalizeResolvedModel,refreshOAuthіaugmentModelCatalog, а такожprepareExtraParams,resolveUsageAuthіfetchUsageSnapshot, оскільки він усе ще працює на транспортах core OpenAI, але володіє нормалізацією свого transport/base URL, політикою fallback для оновлення OAuth, типовим вибором транспорту, synthetic-рядками каталогу Codex та інтеграцією з endpoint usage ChatGPT; він використовує те саме сімейство потоківopenai-responses-defaults, що й прямий OpenAI. - Google AI Studio та Gemini CLI OAuth використовують
resolveDynamicModel,buildReplayPolicy,sanitizeReplayHistory,resolveReasoningOutputMode,wrapStreamFnіisModernModelRef, оскільки сімейство replaygoogle-geminiволодіє fallback прямої сумісності для Gemini 3.1, native-валідацією replay Gemini, санітизацією bootstrap replay, режимом tagged reasoning-output і зіставленням сучасних моделей, тоді як сімейство потоківgoogle-thinkingволодіє нормалізацією payload thinking Gemini; Gemini CLI OAuth також використовуєformatApiKey,resolveUsageAuthіfetchUsageSnapshotдля форматування токена, розбору токена і проводки endpoint quota. - Anthropic Vertex використовує
buildReplayPolicyчерез сімейство replayanthropic-by-model, щоб очищення replay, специфічне для Claude, залишалося в межах id Claude, а не кожного транспортуanthropic-messages. - Amazon Bedrock використовує
buildReplayPolicy,matchesContextOverflowError,classifyFailoverReasonіresolveDefaultThinkingLevel, оскільки він володіє класифікацією помилок throttle/not-ready/context-overflow, специфічною для Bedrock, для трафіку Anthropic-on-Bedrock; його політика replay і далі використовує той самий guardanthropic-by-model, призначений лише для Claude. - OpenRouter, Kilocode, Opencode і Opencode Go використовують
buildReplayPolicyчерез сімейство replaypassthrough-gemini, оскільки вони проксіюють моделі Gemini через транспорти, сумісні з OpenAI, і потребують санітизації thought-signature Gemini без native-валідації replay Gemini або переписувань bootstrap. - MiniMax використовує
buildReplayPolicyчерез сімейство replayhybrid-anthropic-openai, оскільки один провайдер володіє як семантикою повідомлень Anthropic, так і OpenAI-сумісною семантикою; він зберігає відкидання блоків thinking лише для Claude на боці Anthropic, водночас перевизначаючи режим виводу reasoning назад на native, а сімейство потоківminimax-fast-modeволодіє переписуванням моделей fast-mode на спільному шляху потоку. - Moonshot використовує
catalogразом ізwrapStreamFn, оскільки він і далі використовує спільний транспорт OpenAI, але потребує нормалізації payload thinking, що належить провайдеру; сімейство потоківmoonshot-thinkingвідображає config і стан/thinkу його native payload binary thinking. - Kilocode використовує
catalog,capabilities,wrapStreamFnіisCacheTtlEligible, оскільки йому потрібні заголовки запитів, що належать провайдеру, нормалізація payload reasoning, підказки транскриптів Gemini та керування TTL кешу Anthropic; сімейство потоківkilocode-thinkingутримує ін’єкцію thinking Kilo на спільному шляху proxy-потоку, водночас пропускаючиkilo/autoта інші proxy id моделей, які не підтримують явні payload reasoning. - Z.AI використовує
resolveDynamicModel,prepareExtraParams,wrapStreamFn,isCacheTtlEligible,isBinaryThinking,isModernModelRef,resolveUsageAuthіfetchUsageSnapshot, оскільки він володіє fallback для GLM-5, значеннямиtool_streamза замовчуванням, UX binary thinking, зіставленням сучасних моделей і як auth для usage, так і отриманням quota; сімейство потоківtool-stream-default-onутримує обгорткуtool_stream, увімкнену за замовчуванням, поза вручну написаним glue-кодом для кожного провайдера. - xAI використовує
normalizeResolvedModel,normalizeTransport,contributeResolvedModelCompat,prepareExtraParams,wrapStreamFn,resolveSyntheticAuth,resolveDynamicModelіisModernModelRef, оскільки він володіє нормалізацією native-транспорту xAI Responses, переписуванням псевдонімів fast-mode для Grok, типовимtool_stream, очищенням strict-tool / reasoning-payload, повторним використанням fallback auth для інструментів, що належать Plugin, прямим визначенням моделей Grok і compat-патчами, що належать провайдеру, такими як профіль schema інструментів xAI, непідтримувані ключові слова schema, nativeweb_searchі декодування аргументів виклику інструментів із HTML-сутностями. - Mistral, OpenCode Zen і OpenCode Go використовують лише
capabilities, щоб не виносити особливості транскриптів/інструментів у core. - Вбудовані провайдери лише з каталогом, такі як
byteplus,cloudflare-ai-gateway,huggingface,kimi-coding,nvidia,qianfan,synthetic,together,venice,vercel-ai-gatewayіvolcengine, використовують лишеcatalog. - Qwen використовує
catalogдля свого текстового провайдера разом зі спільними реєстраціями розуміння медіа й генерації відео для своїх мультимодальних поверхонь. - MiniMax і Xiaomi використовують
catalogразом із usage-хуками, оскільки їхня поведінка/usageналежить Plugin, хоча сам інференс і далі виконується через спільні транспорти.
Допоміжні засоби runtime
Plugin можуть отримувати доступ до вибраних допоміжних засобів core черезapi.runtime. Для TTS:
textToSpeechповертає звичайне корисне навантаження виводу TTS із core для поверхонь файлів/голосових нотаток.- Використовує конфігурацію core
messages.ttsі вибір провайдера. - Повертає PCM-аудіобуфер + sample rate. Plugin мають виконати повторну дискретизацію/кодування для провайдерів.
listVoicesє необов’язковим для кожного провайдера. Використовуйте його для вибирачів голосу або потоків setup, що належать vendor.- Списки голосів можуть містити багатші метадані, такі як locale, gender і теги personality для вибирачів, обізнаних про провайдера.
- OpenAI і ElevenLabs сьогодні підтримують телефонію. Microsoft — ні.
api.registerSpeechProvider(...).
- Зберігайте політику TTS, fallback і доставку відповіді в core.
- Використовуйте провайдери мовлення для поведінки синтезу, що належить vendor.
- Застарілий вхід Microsoft
edgeнормалізується до id провайдераmicrosoft. - Бажана модель володіння є орієнтованою на компанію: один vendor Plugin може володіти текстовими, мовленнєвими, графічними та майбутніми медіапровайдерами, коли OpenClaw додає відповідні контракти можливостей.
- Зберігайте оркестрацію, fallback, конфігурацію та підключення каналів у core.
- Зберігайте поведінку vendor у Plugin провайдера.
- Адитивне розширення має залишатися типізованим: нові необов’язкові методи, нові необов’язкові поля результату, нові необов’язкові можливості.
- Генерація відео вже дотримується того самого шаблону:
- core володіє контрактом можливості та допоміжним runtime-засобом
- vendor Plugin реєструють
api.registerVideoGenerationProvider(...) - Plugin функцій/каналів споживають
api.runtime.videoGeneration.*
api.runtime.mediaUnderstanding.*— це бажана спільна поверхня для розуміння зображень/аудіо/відео.- Використовує конфігурацію аудіо розуміння медіа з core (
tools.media.audio) і порядок fallback провайдерів. - Повертає
{ text: undefined }, коли вихід транскрибування не створюється (наприклад, у разі пропущеного/непідтримуваного вводу). api.runtime.stt.transcribeAudioFile(...)залишається псевдонімом для сумісності.
api.runtime.subagent:
providerіmodel— це необов’язкові перевизначення для окремого запуску, а не постійні зміни сесії.- OpenClaw враховує ці поля перевизначення лише для довірених викликачів.
- Для запусків fallback, що належать Plugin, оператори мають явно дозволити це через
plugins.entries.<id>.subagent.allowModelOverride: true. - Використовуйте
plugins.entries.<id>.subagent.allowedModels, щоб обмежити довірені Plugin конкретними канонічними цілямиprovider/model, або"*", щоб явно дозволити будь-яку ціль. - Виконання subagent для недовірених Plugin усе одно працюють, але запити на перевизначення відхиляються, а не тихо переходять до fallback.
api.registerWebSearchProvider(...).
Примітки:
- Зберігайте вибір провайдера, визначення облікових даних і спільну семантику запитів у core.
- Використовуйте провайдери вебпошуку для транспортів пошуку, специфічних для vendor.
api.runtime.webSearch.*— це бажана спільна поверхня для Plugin функцій/каналів, яким потрібна поведінка пошуку без залежності від обгортки інструментів агента.
api.runtime.imageGeneration
generate(...): генерує зображення, використовуючи налаштований ланцюжок провайдерів генерації зображень.listProviders(...): перелічує доступні провайдери генерації зображень та їхні можливості.
HTTP-маршрути Gateway
Plugin можуть відкривати HTTP-endpoint-и черезapi.registerHttpRoute(...).
path: шлях маршруту в HTTP-сервері gateway.auth: обов’язкове поле. Використовуйте"gateway", щоб вимагати звичайну auth Gateway, або"plugin"для auth/webhook verification, якими керує Plugin.match: необов’язкове поле."exact"(типово) або"prefix".replaceExisting: необов’язкове поле. Дозволяє тому самому Plugin замінити власну наявну реєстрацію маршруту.handler: повертаєtrue, якщо маршрут обробив запит.
api.registerHttpHandler(...)вилучено, і він спричинить помилку завантаження Plugin. Натомість використовуйтеapi.registerHttpRoute(...).- Маршрути Plugin мають явно оголошувати
auth. - Конфлікти точного
path + matchвідхиляються, якщо не вказаноreplaceExisting: true, і один Plugin не може замінити маршрут іншого Plugin. - Маршрути, що перекриваються та мають різні рівні
auth, відхиляються. Зберігайте ланцюги проходженняexact/prefixлише в межах одного рівня auth. - Маршрути
auth: "plugin"не отримують автоматично runtime-scopes оператора. Вони призначені для webhook-ів/перевірки підписів, якими керує Plugin, а не для привілейованих допоміжних викликів Gateway. - Маршрути
auth: "gateway"працюють у межах runtime-scope запиту Gateway, але цей scope навмисно консервативний:- bearer auth зі спільним секретом (
gateway.auth.mode = "token"/"password") утримує runtime-scopes маршрутів Plugin зафіксованими наoperator.write, навіть якщо викликач надсилаєx-openclaw-scopes - довірені HTTP-режими з ідентичністю (наприклад,
trusted-proxyабоgateway.auth.mode = "none"у приватному ingress) враховуютьx-openclaw-scopesлише тоді, коли цей заголовок явно присутній - якщо
x-openclaw-scopesвідсутній у таких запитах до маршрутів Plugin з ідентичністю, runtime-scope переходить доoperator.write
- bearer auth зі спільним секретом (
- Практичне правило: не вважайте маршрут Plugin із gateway-auth неявною admin-поверхнею. Якщо вашому маршруту потрібна поведінка лише для admin, вимагайте режим auth із носієм ідентичності та задокументуйте явний контракт заголовка
x-openclaw-scopes.
Шляхи імпорту Plugin SDK
Під час створення Plugin використовуйте підшляхи SDK замість монолітного імпортуopenclaw/plugin-sdk:
openclaw/plugin-sdk/plugin-entryдля примітивів реєстрації Plugin.openclaw/plugin-sdk/coreдля узагальненого спільного контракту, орієнтованого на Plugin.openclaw/plugin-sdk/config-schemaдля експорту кореневої схеми Zodopenclaw.json(OpenClawSchema).- Стабільні примітиви каналів, такі як
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, зіставлення згадок, допоміжних засобів політики вхідних згадок, форматування envelope і допоміжних засобів контексту вхідного envelope.channel-setup— це вузький шов setup для необов’язкового встановлення.setup-runtime— це безпечна для runtime поверхня setup, яка використовуєтьсяsetupEntry/ відкладеним запуском, зокрема безпечними для імпорту адаптерами патчів setup.setup-adapter-runtime— це env-aware шов адаптера setup облікового запису.setup-tools— це малий шов допоміжних засобів CLI/архівів/документації (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-gateway-runtime,openclaw/plugin-sdk/approval-handler-adapter-runtime,openclaw/plugin-sdk/approval-handler-runtime,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для спільних допоміжних засобів runtime/config.telegram-command-config— це вузький публічний шов для нормалізації/валідації власних команд Telegram і залишається доступним навіть якщо поверхня контракту вбудованого Telegram тимчасово недоступна.text-runtime— це спільний шов тексту/markdown/логування, зокрема видалення видимого для асистента тексту, допоміжні засоби рендерингу/розбиття markdown, засоби редагування, засоби directive-tag і утиліти безпечного тексту. - Специфічним для схвалення швам каналу слід надавати перевагу одному контракту
approvalCapabilityу Plugin. Тоді core зчитує auth схвалення, доставку, рендеринг, native-routing і ліниву поведінку native-handler через цю одну можливість замість змішування поведінки схвалення з не пов’язаними полями Plugin. openclaw/plugin-sdk/channel-runtimeзастарів і залишається лише як shim сумісності для старіших Plugin. Новий код має імпортувати натомість вужчі узагальнені примітиви, а код репозиторію не повинен додавати нові імпорти цього shim.- Внутрішні механізми вбудованих розширень залишаються приватними. Зовнішні Plugin повинні використовувати лише підшляхи
openclaw/plugin-sdk/*. Код core/test OpenClaw може використовувати публічні точки входу репозиторію в корені пакета Plugin, такі якindex.js,api.js,runtime-api.js,setup-entry.jsі вузькоспрямовані файли, такі якlogin-qr-api.js. Ніколи не імпортуйтеsrc/*пакета Plugin з core або з іншого розширення. - Поділ точок входу репозиторію:
<plugin-package-root>/api.js— це barrel допоміжних засобів/типів,<plugin-package-root>/runtime-api.js— це barrel лише для runtime,<plugin-package-root>/index.js— це точка входу вбудованого Plugin, а<plugin-package-root>/setup-entry.js— це точка входу Plugin для setup. - Поточні приклади вбудованих провайдерів:
- Anthropic використовує
api.js/contract-api.jsдля допоміжних засобів потоку Claude, таких якwrapAnthropicProviderStream, засоби для beta-header і розбірservice_tier. - OpenAI використовує
api.jsдля builder-ів провайдера, допоміжних засобів типових моделей і builder-ів провайдера realtime. - OpenRouter використовує
api.jsдля свого builder-а провайдера разом із допоміжними засобами onboarding/config, тоді якregister.runtime.jsусе ще може повторно експортувати узагальнені допоміжні засобиplugin-sdk/provider-streamдля локального використання в репозиторії.
- Anthropic використовує
- Публічні точки входу, завантажені через facade, надають перевагу активному знімку конфігурації runtime, коли він існує, а потім переходять до визначеного файла конфігурації на диску, коли OpenClaw ще не обслуговує знімок runtime.
- Узагальнені спільні примітиви залишаються бажаним публічним контрактом SDK. Невеликий
зарезервований набір брендових допоміжних швів вбудованих каналів для сумісності все ще існує.
Розглядайте їх як шви для супроводу вбудованих рішень/сумісності, а не як нові цілі імпорту для сторонніх рішень;
нові міжканальні контракти, як і раніше, мають з’являтися у вузьких підшляхах
plugin-sdk/*або в локальних barrelapi.js/runtime-api.jsсамого Plugin.
- Уникайте кореневого barrel
openclaw/plugin-sdkу новому коді. - Спочатку надавайте перевагу вузьким стабільним примітивам. Новіші підшляхи
setup/pairing/reply/feedback/contract/inbound/threading/command/secret-input/webhook/infra/
allowlist/status/message-tool є цільовим контрактом для нової роботи з
вбудованими та зовнішніми Plugin.
Розбір/зіставлення цілей має належати
openclaw/plugin-sdk/channel-targets. Обмеження дій повідомлень і допоміжні засоби message-id для реакцій мають належатиopenclaw/plugin-sdk/channel-actions. - Barrels допоміжних засобів, специфічні для вбудованих розширень, за замовчуванням не є стабільними. Якщо
допоміжний засіб потрібен лише вбудованому розширенню, тримайте його за локальним швом
api.jsабоruntime-api.jsцього розширення замість того, щоб просувати його вopenclaw/plugin-sdk/<extension>. - Нові спільні шви допоміжних засобів мають бути узагальненими, а не брендовими для каналу. Спільний розбір
цілей має належати
openclaw/plugin-sdk/channel-targets; внутрішні механізми, специфічні для каналу, залишаються за локальним швомapi.jsабоruntime-api.jsPlugin-власника. - Підшляхи, специфічні для можливостей, такі як
image-generation,media-understandingіspeech, існують, бо вбудовані/власні Plugin уже використовують їх сьогодні. Їхня наявність сама по собі не означає, що кожен експортований допоміжний засіб є довгостроковим незмінним зовнішнім контрактом.
Схеми інструмента повідомлень
Plugin мають володіти внесками до схемиdescribeMessageTool(...), специфічними для каналу.
Зберігайте поля, специфічні для провайдера, у Plugin, а не в спільному core.
Для спільних переносних фрагментів схем повторно використовуйте узагальнені допоміжні засоби,
експортовані через openclaw/plugin-sdk/channel-actions:
createMessageToolButtonsSchema()для payload у стилі сітки кнопокcreateMessageToolCardSchema()для структурованих payload карток
Визначення цілей каналу
Plugin каналів мають володіти семантикою цілей, специфічною для каналу. Зберігайте спільний хост вихідних повідомлень узагальненим і використовуйте поверхню адаптера повідомлень для правил провайдера:messaging.inferTargetChatType({ to })визначає, чи нормалізовану ціль слід трактувати якdirect,groupабоchannelдо пошуку в директорії.messaging.targetResolver.looksLikeId(raw, normalized)повідомляє core, чи слід вводу одразу перейти до визначення як id-подібної цілі, а не до пошуку в директорії.messaging.targetResolver.resolveTarget(...)— це fallback Plugin, коли core потребує остаточного визначення, що належить провайдеру, після нормалізації або після промаху в директорії.messaging.resolveOutboundSessionRoute(...)володіє побудовою маршруту сесії, специфічного для провайдера, після того як ціль уже визначена.
- Використовуйте
inferTargetChatTypeдля категорійних рішень, які мають відбуватися до пошуку peer/group. - Використовуйте
looksLikeIdдля перевірок «трактувати це як явний/native id цілі». - Використовуйте
resolveTargetдля fallback-нормалізації, специфічної для провайдера, а не для широкого пошуку в директорії. - Зберігайте native id провайдера, такі як id чату, id гілки, JID, handle та id кімнати,
всередині значень
targetабо параметрів, специфічних для провайдера, а не в узагальнених полях SDK.
Директорії на основі конфігурації
Plugin, які виводять записи директорії з конфігурації, мають зберігати цю логіку в Plugin і повторно використовувати спільні допоміжні засоби зopenclaw/plugin-sdk/directory-runtime.
Використовуйте це, коли каналу потрібні peer/group на основі конфігурації, наприклад:
- peer DM на основі allowlist
- налаштовані maps каналів/group
- fallback статичної директорії в межах облікового запису
directory-runtime обробляють лише узагальнені операції:
- фільтрацію запитів
- застосування ліміту
- допоміжні засоби deduping/normalization
- побудову
ChannelDirectoryEntry[]
Каталоги провайдерів
Plugin провайдерів можуть визначати каталоги моделей для інференсу за допомогоюregisterProvider({ catalog: { run(...) { ... } } }).
catalog.run(...) повертає ту саму форму, яку OpenClaw записує в
models.providers:
{ provider }для одного запису провайдера{ providers }для кількох записів провайдерів
catalog, коли Plugin володіє id моделей, базовими значеннями URL або
метаданими моделей, захищеними auth, специфічними для провайдера.
catalog.order керує тим, коли каталог Plugin зливається відносно
вбудованих неявних провайдерів OpenClaw:
simple: прості провайдери з API-ключем або на основі envprofile: провайдери, які з’являються, коли існують профілі authpaired: провайдери, які синтезують кілька пов’язаних записів провайдерівlate: останній прохід, після інших неявних провайдерів
discoveryусе ще працює як застарілий псевдонім- якщо зареєстровано і
catalog, іdiscovery, OpenClaw використовуєcatalog
Інспекція каналу лише для читання
Якщо ваш Plugin реєструє канал, надавайте перевагу реалізаціїplugin.config.inspectAccount(cfg, accountId) разом із resolveAccount(...).
Чому:
resolveAccount(...)— це шлях runtime. Йому дозволено припускати, що облікові дані повністю матеріалізовані, і швидко завершуватися з помилкою, якщо потрібних секретів бракує.- Шляхи команд лише для читання, такі як
openclaw status,openclaw status --all,openclaw channels status,openclaw channels resolve, а також потоки doctor/config repair не повинні вимагати матеріалізації runtime-облікових даних лише для опису конфігурації.
inspectAccount(...):
- Повертайте лише описовий стан облікового запису.
- Зберігайте
enabledіconfigured. - Додавайте поля джерела/стану облікових даних, коли це доречно, наприклад:
tokenSource,tokenStatusbotTokenSource,botTokenStatusappTokenSource,appTokenStatussigningSecretSource,signingSecretStatus
- Вам не потрібно повертати сирі значення токенів лише для повідомлення про
доступність у режимі лише читання. Для команд у стилі status достатньо повертати
tokenStatus: "available"(і відповідне поле джерела). - Використовуйте
configured_unavailable, коли облікові дані налаштовані через SecretRef, але недоступні в поточному шляху команди.
Пакети-pack
Каталог Plugin може міститиpackage.json з openclaw.extensions:
name/<fileBase>.
Якщо ваш Plugin імпортує npm-залежності, встановіть їх у цьому каталозі, щоб
node_modules був доступний (npm install / pnpm install).
Захисне обмеження безпеки: кожен запис openclaw.extensions має залишатися в межах каталогу Plugin
після визначення symlink. Записи, які виходять за межі каталогу пакета,
відхиляються.
Примітка щодо безпеки: openclaw plugins install встановлює залежності Plugin через
npm install --omit=dev --ignore-scripts (без lifecycle scripts і без dev-залежностей під час runtime). Зберігайте дерева залежностей Plugin «чистими JS/TS» і уникайте пакетів, яким потрібні збірки через postinstall.
Необов’язково: openclaw.setupEntry може вказувати на легкий модуль лише для setup.
Коли OpenClaw потребує поверхонь setup для вимкненого Plugin каналу або
коли Plugin каналу ввімкнений, але ще не налаштований, він завантажує setupEntry
замість повної точки входу Plugin. Це зберігає запуск і setup легшими,
коли основна точка входу Plugin також підключає інструменти, хуки чи інший код лише для runtime.
Необов’язково: openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen
може перевести Plugin каналу на той самий шлях setupEntry під час
фази запуску gateway до початку прослуховування, навіть якщо канал уже налаштований.
Використовуйте це лише тоді, коли setupEntry повністю покриває поверхню запуску, яка має існувати
до того, як gateway почне прослуховувати. На практиці це означає, що точка входу setup
має реєструвати кожну можливість, що належить каналу, від якої залежить запуск, наприклад:
- саму реєстрацію каналу
- будь-які HTTP-маршрути, які мають бути доступні до того, як gateway почне прослуховувати
- будь-які методи Gateway, інструменти або сервіси, які мають існувати в тому самому вікні
singleAccountKeysToMovenamedAccountPromotionKeysresolveSingleAccountPromotionTarget(...)
channels.<id>.accounts.* без завантаження повної точки входу Plugin.
Matrix — поточний вбудований приклад: він переміщує лише ключі auth/bootstrap у
іменований просунутий обліковий запис, коли іменовані облікові записи вже існують, і може
зберегти налаштований неканонічний ключ типового облікового запису замість того, щоб завжди створювати
accounts.default.
Ці адаптери патчів setup зберігають ліниве виявлення поверхні контракту вбудованих рішень. Час імпорту
залишається малим; поверхня просування завантажується лише під час першого використання замість
повторного входу в запуск вбудованого каналу під час імпорту модуля.
Коли ці поверхні запуску містять методи Gateway RPC, зберігайте їх на
префіксі, специфічному для Plugin. Простори імен admin core (config.*,
exec.approvals.*, wizard.*, update.*) залишаються зарезервованими й завжди визначаються
як operator.admin, навіть якщо Plugin запитує вужчий scope.
Приклад:
Метадані каталогу каналів
Plugin каналів можуть оголошувати метадані setup/discovery черезopenclaw.channel і
підказки встановлення через openclaw.install. Це дозволяє не тримати дані каталогу в core.
Приклад:
openclaw.channel, окрім мінімального прикладу:
detailLabel: вторинна мітка для багатших поверхонь каталогу/статусуdocsLabel: перевизначення тексту посилання для посилання на документаціюpreferOver: id Plugin/каналів із нижчим пріоритетом, які цей запис каталогу має перевершуватиselectionDocsPrefix,selectionDocsOmitLabel,selectionExtras: керування текстом поверхні виборуmarkdownCapable: позначає канал як сумісний із markdown для рішень форматування вихідних повідомленьexposure.configured: приховує канал із поверхонь списку налаштованих каналів, якщо встановленоfalseexposure.setup: приховує канал з інтерактивних вибирачів setup/configure, якщо встановленоfalseexposure.docs: позначає канал як внутрішній/приватний для поверхонь навігації документаціїshowConfigured/showInSetup: застарілі псевдоніми, які все ще приймаються для сумісності; надавайте перевагуexposurequickstartAllowFrom: додає канал до стандартного потоку quickstartallowFromforceAccountBinding: вимагає явного прив’язування облікового запису, навіть якщо існує лише один обліковий записpreferSessionLookupForAnnounceTarget: надає перевагу пошуку сесії під час визначення announce target
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
OPENCLAW_PLUGIN_CATALOG_PATHS (або OPENCLAW_MPM_CATALOG_PATHS) на
один чи кілька JSON-файлів (розділених комою/крапкою з комою/роздільником PATH). Кожен файл має
містити { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }. Парсер також приймає "packages" або "plugins" як застарілі псевдоніми для ключа "entries".
Plugin рушія контексту
Plugin рушія контексту володіють оркестрацією контексту сесії для ingest, assembly і Compaction. Реєструйте їх зі свого Plugin черезapi.registerContextEngine(id, factory), а потім вибирайте активний рушій через
plugins.slots.contextEngine.
Використовуйте це, коли вашому Plugin потрібно замінити або розширити типовий
конвеєр контексту, а не просто додати пошук у пам’яті чи хуки.
compact()
реалізованим і явно делегуйте його:
Додавання нової можливості
Коли Plugin потребує поведінки, яка не вписується в поточний API, не обходьте систему Plugin через приватне звернення всередину. Додайте відсутню можливість. Рекомендована послідовність:- визначте контракт core Вирішіть, якою спільною поведінкою має володіти core: політика, fallback, злиття конфігурації, життєвий цикл, семантика для каналів і форма допоміжного runtime-засобу.
- додайте типізовані поверхні реєстрації/runtime для Plugin
Розширте
OpenClawPluginApiі/абоapi.runtimeнайменшою корисною типізованою поверхнею можливості. - під’єднайте споживачів core + каналів/функцій Канали та Plugin функцій мають споживати нову можливість через core, а не імпортуючи реалізацію vendor напряму.
- зареєструйте реалізації vendor Потім vendor Plugin реєструють свої backends для цієї можливості.
- додайте покриття контрактів Додайте тести, щоб володіння і форма реєстрації з часом залишалися явними.
Контрольний список можливості
Коли ви додаєте нову можливість, реалізація зазвичай має одночасно торкатися таких поверхонь:- типи контракту core в
src/<capability>/types.ts - runner/допоміжний runtime-засіб core в
src/<capability>/runtime.ts - поверхня реєстрації API Plugin в
src/plugins/types.ts - підключення реєстру Plugin в
src/plugins/registry.ts - відкриття runtime Plugin у
src/plugins/runtime/*, коли Plugin функцій/каналів мають це споживати - допоміжні засоби capture/test у
src/test-utils/plugin-registration.ts - перевірки володіння/контрактів у
src/plugins/contracts/registry.ts - документація для операторів/Plugin у
docs/
Шаблон можливості
Мінімальний шаблон:- core володіє контрактом можливості + оркестрацією
- vendor Plugin володіють реалізаціями vendor
- Plugin функцій/каналів споживають допоміжні runtime-засоби
- тести контрактів зберігають явність володіння