Building plugins
Pluginy narzędziowe
Pluginy narzędzi dodają do OpenClaw narzędzia wywoływalne przez agenta bez dodawania kanału,
dostawcy modeli, hooka, usługi ani backendu konfiguracji. Użyj defineToolPlugin, gdy
plugin posiada stałą listę narzędzi i chcesz, aby OpenClaw wygenerował metadane manifestu,
dzięki którym te narzędzia pozostają wykrywalne bez ładowania kodu uruchomieniowego.
Zalecany przepływ wygląda tak:
- Utwórz szkielet pakietu za pomocą
openclaw plugins init. - Napisz narzędzia z
defineToolPlugin. - Zbuduj JavaScript.
- Wygeneruj metadane
openclaw.plugin.jsonipackage.jsonza pomocąopenclaw plugins build. - Zweryfikuj wygenerowane metadane przed publikacją lub instalacją.
Dla pluginów dostawców, kanałów, hooków, usług albo pluginów o mieszanych możliwościach zacznij zamiast tego od Tworzenie pluginów, Pluginy kanałów albo Pluginy dostawców.
Wymagania
- Node >= 22.
- Wyjście pakietu TypeScript ESM.
typeboxdla schematów konfiguracji i parametrów narzędzi.openclaw >=2026.5.17, pierwsza wersja OpenClaw eksportującaopenclaw/plugin-sdk/tool-plugin.- Katalog główny pakietu, który może dostarczać
dist/,openclaw.plugin.jsonipackage.json.
Wygenerowany plugin importuje typebox w czasie uruchomienia, więc trzymaj typebox w
dependencies, nie tylko w devDependencies.
Szybki start
Utwórz nowy pakiet pluginu:
openclaw plugins init stock-quotes --name "Stock Quotes"cd stock-quotesnpm installnpm run plugin:buildnpm run plugin:validatenpm testSzkielet tworzy:
src/index.ts: punkt wejściadefineToolPluginz narzędziemecho.src/index.test.ts: mały test metadanych.tsconfig.json: wyjście TypeScript NodeNext dodist/.package.json: skrypty, zależności uruchomieniowe iopenclaw.extensions: ["./dist/index.js"].openclaw.plugin.json: wygenerowane metadane manifestu dla początkowego narzędzia.
Oczekiwane wyjście walidacji:
Plugin stock-quotes is valid.Napisz narzędzie
defineToolPlugin przyjmuje tożsamość pluginu, opcjonalny schemat konfiguracji i
statyczną listę narzędzi. Typy parametrów i konfiguracji są wnioskowane ze schematów
TypeBox.
export default defineToolPlugin({ id: "stock-quotes", name: "Stock Quotes", description: "Fetch stock quote snapshots.", configSchema: Type.Object({ apiKey: Type.Optional(Type.String({ description: "Quote API key." })), baseUrl: Type.Optional(Type.String({ description: "Quote API base URL." })), }), tools: (tool) => [ tool({ name: "stock_quote", label: "Stock Quote", description: "Fetch a stock quote snapshot.", parameters: Type.Object({ symbol: Type.String({ description: "Ticker symbol, for example OPEN." }), }), async execute({ symbol }, config, context) { context.signal?.throwIfAborted(); return { symbol: symbol.toUpperCase(), configured: Boolean(config.apiKey), baseUrl: config.baseUrl ?? "https://api.example.com", }; }, }), ],});Nazwy narzędzi są stabilnym API. Wybieraj nazwy unikalne, pisane małymi literami i wystarczająco konkretne, aby uniknąć kolizji z narzędziami rdzenia lub innymi pluginami.
Narzędzia opcjonalne i fabryczne
Ustaw optional: true, gdy użytkownicy powinni jawnie dodać narzędzie do listy dozwolonych,
zanim zostanie wysłane do modelu:
tool({ name: "workflow_run", description: "Run an external workflow.", parameters: Type.Object({ goal: Type.String() }), optional: true, execute: ({ goal }) => ({ queued: true, goal }),});openclaw plugins build zapisuje odpowiadający wpis manifestu toolMetadata.<tool>.optional,
dzięki czemu OpenClaw może wykryć narzędzie bez ładowania kodu uruchomieniowego
pluginu.
Użyj factory, gdy narzędzie potrzebuje kontekstu narzędzia uruchomieniowego, zanim może
zostać utworzone. Fabryka utrzymuje statyczne metadane, jednocześnie pozwalając narzędziu wyłączyć się dla
konkretnego uruchomienia, sprawdzić stan piaskownicy albo powiązać pomocniki uruchomieniowe.
tool({ name: "local_workflow", description: "Run a local workflow outside sandboxed sessions.", parameters: Type.Object({ goal: Type.String() }), optional: true, factory({ api, toolContext }) { if (toolContext.sandboxed) { return null; } return createLocalWorkflowTool(api); },});Fabryki nadal są przeznaczone dla stałych nazw narzędzi. Użyj bezpośrednio definePluginEntry, gdy
plugin oblicza nazwy narzędzi dynamicznie albo łączy narzędzia z hookami,
usługami, dostawcami, poleceniami lub innymi powierzchniami uruchomieniowymi.
Wartości zwracane
defineToolPlugin opakowuje zwykłe wartości zwracane w format wyniku narzędzia
OpenClaw:
- Zwróć ciąg znaków, gdy model powinien zobaczyć dokładnie ten tekst.
- Zwróć wartość zgodną z JSON, gdy chcesz, aby model zobaczył sformatowany JSON,
a OpenClaw zachował oryginalną wartość w
details.
tool({ name: "echo_text", description: "Echo input text.", parameters: Type.Object({ input: Type.String(), }), execute: ({ input }) => input,});tool({ name: "echo_json", description: "Echo input as structured JSON.", parameters: Type.Object({ input: Type.String(), }), execute: ({ input }) => ({ input, length: input.length }),});Użyj narzędzia fabrycznego, gdy musisz zwrócić niestandardowy AgentToolResult albo ponownie użyć
istniejącej implementacji api.registerTool. Użyj definePluginEntry zamiast
defineToolPlugin, gdy potrzebujesz w pełni dynamicznych narzędzi albo mieszanych
możliwości pluginu.
Konfiguracja
configSchema jest opcjonalny. Jeśli go pominiesz, OpenClaw użyje ścisłego schematu
pustego obiektu, a wygenerowany manifest nadal będzie zawierać configSchema.
export default defineToolPlugin({ id: "no-config-tools", name: "No Config Tools", description: "Adds tools that do not need configuration.", tools: () => [],});Gdy dołączysz configSchema, drugi argument execute jest typowany na podstawie
schematu:
const configSchema = Type.Object({ apiKey: Type.String(),}); export default defineToolPlugin({ id: "configured-tools", name: "Configured Tools", description: "Adds configured tools.", configSchema, tools: (tool) => [ tool({ name: "configured_ping", description: "Check whether configuration is available.", parameters: Type.Object({}), execute: (_params, config) => ({ hasKey: config.apiKey.length > 0 }), }), ],});OpenClaw odczytuje konfigurację pluginu z wpisu pluginu w konfiguracji Gateway. Nie wpisuj sekretów na stałe w kodzie źródłowym ani w przykładach dokumentacji. Używaj konfiguracji, zmiennych środowiskowych albo SecretRefs zgodnie z modelem bezpieczeństwa pluginu.
Wygenerowane metadane
OpenClaw wykrywa zainstalowane pluginy z zimnych metadanych. Musi być w stanie odczytać
manifest pluginu przed zaimportowaniem kodu uruchomieniowego pluginu. Dlatego defineToolPlugin
udostępnia statyczne metadane, a openclaw plugins build zapisuje te
metadane w pakiecie.
Uruchom generator po zmianie identyfikatora pluginu, nazwy, opisu, schematu konfiguracji, aktywacji lub nazw narzędzi:
npm run buildopenclaw plugins build --entry ./dist/index.jsDla pluginu z jednym narzędziem wygenerowany manifest wygląda tak:
{ "id": "stock-quotes", "name": "Stock Quotes", "description": "Fetch stock quote snapshots.", "version": "0.1.0", "configSchema": { "type": "object", "additionalProperties": false, "properties": {} }, "activation": { "onStartup": true }, "contracts": { "tools": ["stock_quote"] }}contracts.tools jest ważnym kontraktem wykrywania. Informuje OpenClaw, który
plugin posiada każde narzędzie, bez ładowania każdego zainstalowanego środowiska uruchomieniowego pluginu. Jeśli
manifest jest nieaktualny, narzędzia może brakować w wykrywaniu albo za błąd
rejestracji może zostać obwiniony niewłaściwy plugin.
Metadane pakietu
Dla prostego przepływu pluginu narzędziowego openclaw plugins build uzgadnia
package.json z wybranym pojedynczym punktem wejścia uruchomieniowego:
{ "type": "module", "files": ["dist", "openclaw.plugin.json", "README.md"], "dependencies": { "typebox": "^1.1.38" }, "peerDependencies": { "openclaw": ">=2026.5.17" }, "openclaw": { "extensions": ["./dist/index.js"] }}Dla zainstalowanych pakietów używaj zbudowanego JavaScriptu, takiego jak ./dist/index.js. Wpisy
źródłowe są przydatne podczas programowania w workspace, ale opublikowane pakiety nie powinny
zależeć od ładowania TypeScriptu w czasie uruchomienia.
Walidacja w CI
Użyj plugins build --check, aby CI zakończyło się błędem, gdy wygenerowane metadane są nieaktualne, bez
przepisywania plików:
npm run buildopenclaw plugins build --entry ./dist/index.js --checkopenclaw plugins validate --entry ./dist/index.jsnpm testplugins validate sprawdza, że:
openclaw.plugin.jsonistnieje i przechodzi przez standardowy loader manifestu.- Bieżący punkt wejścia eksportuje metadane
defineToolPlugin. - Wygenerowane pola manifestu pasują do metadanych punktu wejścia.
contracts.toolspasuje do zadeklarowanych nazw narzędzi.package.jsonwskazujeopenclaw.extensionsna wybrany punkt wejścia uruchomieniowego.
Instalacja i lokalna inspekcja
Z oddzielnego checkoutu OpenClaw albo zainstalowanego CLI zainstaluj ścieżkę pakietu:
openclaw plugins install ./stock-quotesopenclaw plugins inspect stock-quotes --runtimeDla pakietowego smoke testu najpierw spakuj, a potem zainstaluj archiwum tarball:
npm packopenclaw plugins install npm-pack:./openclaw-plugin-stock-quotes-0.1.0.tgzopenclaw plugins inspect stock-quotes --runtime --jsonPo instalacji uruchom lub zrestartuj Gateway i poproś agenta o użycie narzędzia. Jeśli debugujesz widoczność narzędzia, sprawdź środowisko uruchomieniowe pluginu i efektywny katalog narzędzi przed zmianą kodu.
Publikacja
Publikuj przez ClawHub, gdy pakiet jest gotowy:
clawhub package publish your-org/stock-quotes --dry-runclawhub package publish your-org/stock-quotesZainstaluj z jawnym lokatorem ClawHub:
openclaw plugins install clawhub:your-org/stock-quotesSame specyfikacje pakietów npm pozostają obsługiwane podczas przejścia startowego, ale ClawHub jest preferowaną powierzchnią wykrywania i dystrybucji dla pluginów OpenClaw.
Rozwiązywanie problemów
plugin entry not found: ./dist/index.js
Wybrany plik punktu wejścia nie istnieje. Uruchom npm run build, a następnie ponownie uruchom
openclaw plugins build --entry ./dist/index.js albo
openclaw plugins validate --entry ./dist/index.js.
plugin entry does not expose defineToolPlugin metadata
Punkt wejścia nie wyeksportował wartości utworzonej przez defineToolPlugin. Sprawdź, czy
domyślny eksport modułu jest wynikiem defineToolPlugin(...), albo przekaż poprawny
punkt wejścia przez --entry.
openclaw.plugin.json generated metadata is stale
Manifest nie pasuje już do metadanych punktu wejścia. Uruchom:
npm run buildopenclaw plugins build --entry ./dist/index.jsZacommituj zmiany w openclaw.plugin.json i package.json.
package.json openclaw.extensions must include ./dist/index.js
Metadane pakietu wskazują inny punkt wejścia uruchomieniowego. Uruchom
openclaw plugins build --entry ./dist/index.js, aby generator uzgodnił
metadane pakietu z punktem wejścia, który zamierzasz dostarczyć.
Cannot find package 'typebox'
Zbudowany plugin importuje typebox w czasie uruchomienia. Trzymaj typebox w
dependencies, zainstaluj ponownie zależności pakietu, zbuduj ponownie i ponownie uruchom walidację.
Narzędzie nie pojawia się po instalacji
Sprawdź te elementy w kolejności:
openclaw plugins inspect <plugin-id> --runtimeopenclaw plugins validate --root <plugin-root> --entry ./dist/index.jsopenclaw.plugin.jsonmacontracts.toolsz oczekiwanymi nazwami narzędzi.package.jsonmaopenclaw.extensions: ["./dist/index.js"].- Gateway został zrestartowany lub przeładowany po zainstalowaniu pluginu.