Plugins (Extensions)

Bắt đầu nhanh (mới làm quen với plugins?)

Plugin chỉ là một module code nhỏ mở rộng OpenClaw với các tính năng bổ sung (lệnh, công cụ và Gateway RPC).

Hầu hết thời gian, các bạn sẽ dùng plugins khi muốn một tính năng chưa được tích hợp sẵn trong OpenClaw core (hoặc muốn giữ các tính năng tùy chọn tách khỏi bản cài đặt chính).

Cách nhanh:

  1. Xem những gì đã được tải:
openclaw plugins list
  1. Cài đặt một plugin chính thức (ví dụ: Voice Call):
openclaw plugins install @openclaw/voice-call
  1. Khởi động lại Gateway, sau đó cấu hình trong plugins.entries.<id>.config.

Xem Voice Call để tham khảo ví dụ plugin cụ thể.

Các plugin có sẵn (chính thức)

  • Microsoft Teams chỉ có dạng plugin từ 2026.1.15; cài @openclaw/msteams nếu các bạn dùng Teams.
  • Memory (Core) — plugin tìm kiếm bộ nhớ đi kèm (bật mặc định qua plugins.slots.memory)
  • Memory (LanceDB) — plugin bộ nhớ dài hạn đi kèm (tự động ghi nhớ/lưu trữ; đặt plugins.slots.memory = "memory-lancedb")
  • Voice Call@openclaw/voice-call
  • Zalo Personal@openclaw/zalouser
  • Matrix@openclaw/matrix
  • Nostr@openclaw/nostr
  • Zalo@openclaw/zalo
  • Microsoft Teams@openclaw/msteams
  • Google Antigravity OAuth (provider auth) — đi kèm dưới tên google-antigravity-auth (tắt mặc định)
  • Gemini CLI OAuth (provider auth) — đi kèm dưới tên google-gemini-cli-auth (tắt mặc định)
  • Qwen OAuth (provider auth) — đi kèm dưới tên qwen-portal-auth (tắt mặc định)
  • Copilot Proxy (provider auth) — cầu nối VS Code Copilot Proxy cục bộ; khác với đăng nhập thiết bị github-copilot tích hợp sẵn (đi kèm, tắt mặc định)

OpenClaw plugins là TypeScript modules được tải lúc runtime qua jiti. Xác thực config không thực thi code plugin; nó dùng plugin manifest và JSON Schema thay thế. Xem Plugin manifest.

Plugins có thể đăng ký:

  • Gateway RPC methods
  • Gateway HTTP handlers
  • Agent tools
  • CLI commands
  • Background services
  • Xác thực config tùy chọn
  • Skills (bằng cách liệt kê thư mục skills trong plugin manifest)
  • Auto-reply commands (thực thi mà không cần gọi AI agent)

Plugins chạy in-process với Gateway, nên hãy coi chúng như code đáng tin cậy. Hướng dẫn viết công cụ: Plugin agent tools.

Runtime helpers

Plugins có thể truy cập các helper core đã chọn qua api.runtime. Cho telephony TTS:

const result = await api.runtime.tts.textToSpeechTelephony({
  text: "Hello from OpenClaw",
  cfg: api.config,
});

Lưu ý:

  • Dùng cấu hình messages.tts core (OpenAI hoặc ElevenLabs).
  • Trả về PCM audio buffer + sample rate. Plugins phải resample/encode cho providers.
  • Edge TTS không được hỗ trợ cho telephony.

Discovery & precedence

OpenClaw quét theo thứ tự:

  1. Config paths
  • plugins.load.paths (file hoặc thư mục)
  1. Workspace extensions
  • <workspace>/.openclaw/extensions/*.ts
  • <workspace>/.openclaw/extensions/*/index.ts
  1. Global extensions
  • ~/.openclaw/extensions/*.ts
  • ~/.openclaw/extensions/*/index.ts
  1. Bundled extensions (đi kèm với OpenClaw, tắt mặc định)
  • <openclaw>/extensions/*

Bundled plugins phải được bật rõ ràng qua plugins.entries.<id>.enabled hoặc openclaw plugins enable <id>. Installed plugins được bật mặc định, nhưng có thể tắt theo cách tương tự.

Mỗi plugin phải có file openclaw.plugin.json trong thư mục gốc của nó. Nếu đường dẫn trỏ đến một file, thư mục gốc plugin là thư mục chứa file đó và phải có manifest.

Nếu nhiều plugins cùng resolve về một id, kết quả khớp đầu tiên theo thứ tự trên sẽ thắng và các bản sao ưu tiên thấp hơn bị bỏ qua.

Package packs

Một thư mục plugin có thể bao gồm package.json với openclaw.extensions:

{
  "name": "my-pack",
  "openclaw": {
    "extensions": ["./src/safety.ts", "./src/tools.ts"]
  }
}

Mỗi entry trở thành một plugin. Nếu pack liệt kê nhiều extensions, plugin id sẽ trở thành name/<fileBase>.

Nếu plugin của các bạn import npm deps, hãy cài chúng trong thư mục đó để node_modules có sẵn (npm install / pnpm install).

Channel catalog metadata

Channel plugins có thể quảng cáo metadata onboarding qua openclaw.channel và gợi ý cài đặt qua openclaw.install. Điều này giữ cho core catalog không có dữ liệu.

Ví dụ:

{
  "name": "@openclaw/nextcloud-talk",
  "openclaw": {
    "extensions": ["./index.ts"],
    "channel": {
      "id": "nextcloud-talk",
      "label": "Nextcloud Talk",
      "selectionLabel": "Nextcloud Talk (self-hosted)",
      "docsPath": "/channels/nextcloud-talk",
      "docsLabel": "nextcloud-talk",
      "blurb": "Self-hosted chat via Nextcloud Talk webhook bots.",
      "order": 65,
      "aliases": ["nc-talk", "nc"]
    },
    "install": {
      "npmSpec": "@openclaw/nextcloud-talk",
      "localPath": "extensions/nextcloud-talk",
      "defaultChoice": "npm"
    }
  }
}

OpenClaw cũng có thể merge external channel catalogs (ví dụ, một MPM registry export). Đặt file JSON tại một trong các vị trí:

  • ~/.openclaw/mpm/plugins.json
  • ~/.openclaw/mpm/catalog.json
  • ~/.openclaw/plugins/catalog.json

Hoặc trỏ OPENCLAW_PLUGIN_CATALOG_PATHS (hoặc OPENCLAW_MPM_CATALOG_PATHS) đến một hoặc nhiều file JSON (phân cách bằng dấu phẩy/chấm phẩy/PATH). Mỗi file nên chứa { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }.

Plugin IDs

Plugin ids mặc định:

  • Package packs: name trong package.json
  • Standalone file: tên base của file (~/.../voice-call.tsvoice-call)

Nếu plugin export id, OpenClaw sẽ dùng nó nhưng cảnh báo khi nó không khớp với id đã cấu hình.

Config

{
  plugins: {
    enabled: true,
    allow: ["voice-call"],
    deny: ["untrusted-plugin"],
    load: { paths: ["~/Projects/oss/voice-call-extension"] },
    entries: {
      "voice-call": { enabled: true, config: { provider: "twilio" } },
    },
  },
}

Các trường:

  • enabled: công tắc chính (mặc định: true)
  • allow: danh sách cho phép (tùy chọn)
  • deny: danh sách từ chối (tùy chọn; deny thắng)
  • load.paths: file/thư mục plugin bổ sung
  • entries.<id>: công tắc + config cho từng plugin

Thay đổi config yêu cầu khởi động lại gateway.

Quy tắc xác thực (nghiêm ngặt):

  • Plugin ids không xác định trong entries, allow, deny, hoặc slotslỗi.
  • Các key channels.<id> không xác định là lỗi trừ khi plugin manifest khai báo channel id đó.
  • Config plugin được xác thực bằng JSON Schema nhúng trong openclaw.plugin.json (configSchema).
  • Nếu plugin bị tắt, config của nó được giữ lại và một cảnh báo được phát ra.

Plugin slots (exclusive categories)

Một số danh mục plugin là exclusive (chỉ một plugin hoạt động tại một thời điểm). Dùng plugins.slots để chọn plugin nào sở hữu slot:

{
  plugins: {
    slots: {
      memory: "memory-core", // hoặc "none" để tắt memory plugins
    },
  },
}

Nếu nhiều plugins khai báo kind: "memory", chỉ plugin được chọn mới tải. Các plugin khác bị tắt với diagnostics.

Control UI (schema + labels)

Control UI dùng config.schema (JSON Schema + uiHints) để render form tốt hơn.

OpenClaw bổ sung uiHints lúc runtime dựa trên các plugin đã khám phá:

  • Thêm labels cho từng plugin cho plugins.entries.<id> / .enabled / .config
  • Merge các gợi ý trường config tùy chọn do plugin cung cấp dưới: plugins.entries.<id>.config.<field>

Nếu các bạn muốn các trường config plugin hiển thị labels/placeholders tốt (và đánh dấu secrets là sensitive), hãy cung cấp uiHints cùng với JSON Schema trong plugin manifest.

Ví dụ:

{
  "id": "my-plugin",
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "apiKey": { "type": "string" },
      "region": { "type": "string" }
    }
  },
  "uiHints": {
    "apiKey": { "label": "API Key", "sensitive": true },
    "region": { "label": "Region", "placeholder": "us-east-1" }
  }
}

CLI

openclaw plugins list
openclaw plugins info <id>
openclaw plugins install <path>                 # copy file/thư mục cục bộ vào ~/.openclaw/extensions/<id>
openclaw plugins install ./extensions/voice-call # đường dẫn tương đối ok
openclaw plugins install ./plugin.tgz           # cài từ tarball cục bộ
openclaw plugins install ./plugin.zip           # cài từ zip cục bộ
openclaw plugins install -l ./extensions/voice-call # link (không copy) cho dev
openclaw plugins install @openclaw/voice-call # cài từ npm
openclaw plugins update <id>
openclaw plugins update --all
openclaw plugins enable <id>
openclaw plugins disable <id>
openclaw plugins doctor

plugins update chỉ hoạt động cho các bản cài npm được theo dõi trong plugins.installs.

Plugins cũng có thể đăng ký các lệnh top-level riêng (ví dụ: openclaw voicecall).

Plugin API (tổng quan)

Plugins export một trong hai:

  • Một function: (api) => { ... }
  • Một object: { id, name, configSchema, register(api) { ... } }

Plugin hooks

Plugins có thể đi kèm hooks và đăng ký chúng lúc runtime. Điều này cho phép plugin đóng gói automation hướng sự kiện mà không cần cài đặt hook pack riêng.

Ví dụ

import { registerPluginHooksFromDir } from "openclaw/plugin-sdk";

export default function register(api) {
  registerPluginHooksFromDir(api, "./hooks");
}

Lưu ý:

  • Thư mục hooks tuân theo cấu trúc hook thông thường (HOOK.md + handler.ts).
  • Quy tắc điều kiện hook vẫn áp dụng (yêu cầu OS/bins/env/config).
  • Hooks do plugin quản lý hiển thị trong openclaw hooks list với plugin:<id>.
  • Các bạn không thể bật/tắt hooks do plugin quản lý qua openclaw hooks; thay vào đó hãy bật/tắt plugin.

Provider plugins (model auth)

Plugins có thể đăng ký model provider auth flows để người dùng có thể chạy OAuth hoặc thiết lập API-key bên trong OpenClaw (không cần script bên ngoài).

Đăng ký provider qua api.registerProvider(...). Mỗi provider cung cấp một hoặc nhiều phương thức auth (OAuth, API key, device code, v.v.). Các phương thức này hỗ trợ:

  • openclaw models auth login --provider <id> [--method <id>]

Ví dụ:

api.registerProvider({
  id: "acme",
  label: "AcmeAI",
  auth: [
    {
      id: "oauth",
      label: "OAuth",
      kind: "oauth",
      run: async (ctx) => {
        // Chạy OAuth flow và trả về auth profiles.
        return {
          profiles: [
            {
              profileId: "acme:default",
              credential: {
                type: "oauth",
                provider: "acme",
                access: "...",
                refresh: "...",
                expires: Date.now() + 3600 * 1000,
              },
            },
          ],
          defaultModel: "acme/opus-1",
        };
      },
    },
  ],
});

Lưu ý:

  • run nhận ProviderAuthContext với các helper prompter, runtime, openUrl, và oauth.createVpsAwareHandlers.
  • Trả về configPatch khi các bạn cần thêm models mặc định hoặc provider config.
  • Trả về defaultModel để --set-default có thể cập nhật agent defaults.

Đăng ký messaging channel

Plugins có thể đăng ký channel plugins hoạt động như các channels tích hợp sẵn (WhatsApp, Telegram, v.v.). Config channel nằm dưới channels.<id> và được xác thực bởi code channel plugin của các bạn.

const myChannel = {
  id: "acmechat",
  meta: {
    id: "acmechat",
    label: "AcmeChat",
    selectionLabel: "AcmeChat (API)",
    docsPath: "/channels/acmechat",
    blurb: "demo channel plugin.",
    aliases: ["acme"],
  },
  capabilities: { chatTypes: ["direct"] },
  config: {
    listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
    resolveAccount: (cfg, accountId) =>
      cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
        accountId,
      },
  },
  outbound: {
    deliveryMode: "direct",
    sendText: async () => ({ ok: true }),
  },
};

export default function (api) {
  api.registerChannel({ plugin: myChannel });
}

Lưu ý:

  • Đặt config dưới channels.<id> (không phải plugins.entries).
  • meta.label được dùng cho labels trong danh sách CLI/UI.
  • meta.aliases thêm các id thay thế cho normalization và CLI inputs.
  • meta.preferOver liệt kê các channel ids để bỏ qua auto-enable khi cả hai được cấu hình.
  • meta.detailLabelmeta.systemImage cho phép UIs hiển thị labels/icons channel phong phú hơn.

Viết messaging channel mới (từng bước)

Dùng cái này khi các bạn muốn một chat surface mới (một “messaging channel”), không phải model provider. Tài liệu model provider nằm dưới /providers/*.

  1. Chọn id + hình dạng config
  • Tất cả config channel nằm dưới channels.<id>.
  • Ưu tiên channels.<id>.accounts.<accountId> cho thiết lập multi-account.
  1. Định nghĩa metadata channel
  • meta.label, meta.selectionLabel, meta.docsPath, meta.blurb điều khiển danh sách CLI/UI.
  • meta.docsPath nên trỏ đến trang docs như /channels/<id>.
  • meta.preferOver cho phép plugin thay thế channel khác (auto-enable ưu tiên nó).
  • meta.detailLabelmeta.systemImage được UIs dùng cho text/icons chi tiết.
  1. Implement các adapters bắt buộc
  • config.listAccountIds + config.resolveAccount
  • capabilities (chat types, media, threads, v.v.)
  • outbound.deliveryMode + outbound.sendText (cho gửi cơ bản)
  1. Thêm adapters tùy chọn khi cần
  • setup (wizard), security (DM policy), status (health/diagnostics)
  • gateway (start/stop/login), mentions, threading, streaming
  • actions (message actions), commands (native command behavior)
  1. Đăng ký channel trong plugin của các bạn
  • api.registerChannel({ plugin })

Ví dụ config tối thiểu:

{
  channels: {
    acmechat: {
      accounts: {
        default: { token: "ACME_TOKEN", enabled: true },
      },
    },
  },
}

Channel plugin tối thiểu (chỉ outbound):

const plugin = {
  id: "acmechat",
  meta: {
    id: "acmechat",
    label: "AcmeChat",
    selectionLabel: "AcmeChat (API)",
    docsPath: "/channels/acmechat",
    blurb: "AcmeChat messaging channel.",
    aliases: ["acme"],
  },
  capabilities: { chatTypes: ["direct"] },
  config: {
    listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
    resolveAccount: (cfg, accountId) =>
      cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? {
        accountId,
      },
  },
  outbound: {
    deliveryMode: "direct",
    sendText: async ({ text }) => {
      // gửi `text` đến channel của các bạn ở đây
      return { ok: true };
    },
  },
};

export default function (api) {
  api.registerChannel({ plugin });
}

Tải plugin (thư mục extensions hoặc plugins.load.paths), khởi động lại gateway, sau đó cấu hình channels.<id> trong config của các bạn.

Agent tools

Xem hướng dẫn chuyên biệt: Plugin agent tools.

Đăng ký gateway RPC method

export default function (api) {
  api.registerGatewayMethod("myplugin.status", ({ respond }) => {
    respond(true, { ok: true });
  });
}

Đăng ký CLI commands

export default function (api) {
  api.registerCli(
    ({ program }) => {
      program.command("mycmd").action(() => {
        console.log("Hello");
      });
    },
    { commands: ["mycmd"] },
  );
}

Đăng ký auto-reply commands

Plugins có thể đăng ký các slash commands tùy chỉnh thực thi mà không cần gọi AI agent. Điều này hữu ích cho các lệnh toggle, kiểm tra trạng thái, hoặc hành động nhanh không cần xử lý LLM.

export default function (api) {
  api.registerCommand({
    name: "mystatus",
    description: "Show plugin status",
    handler: (ctx) => ({
      text: `Plugin is running! Channel: ${ctx.channel}`,
    }),
  });
}

Command handler context:

  • senderId: ID của người gửi (nếu có)
  • channel: Channel nơi lệnh được gửi
  • isAuthorizedSender: Người gửi có phải là người dùng được ủy quyền không
  • args: Các đối số được truyền sau lệnh (nếu acceptsArgs: true)
  • commandBody: Toàn bộ text lệnh
  • config: Config OpenClaw hiện tại

Command options:

  • name: Tên lệnh (không có dấu / đầu)
  • description: Text trợ giúp hiển thị trong danh sách lệnh
  • acceptsArgs: Lệnh có chấp nhận đối số không (mặc định: false). Nếu false và có đối số được cung cấp, lệnh sẽ không khớp và message rơi vào các handlers khác
  • requireAuth: Có yêu cầu người gửi được ủy quyền không (mặc định: true)
  • handler: Function trả về { text: string } (có thể async)

Ví dụ với authorization và arguments:

api.registerCommand({
  name: "setmode",
  description: "Set plugin mode",
  acceptsArgs: true,
  requireAuth: true,
  handler: async (ctx) => {
    const mode = ctx.args?.trim() || "default";
    await saveMode(mode);
    return { text: `Mode set to: ${mode}` };
  },
});

Lưu ý:

  • Plugin commands được xử lý trước built-in commands và AI agent
  • Commands được đăng ký globally và hoạt động trên tất cả channels
  • Tên lệnh không phân biệt chữ hoa chữ thường (/MyStatus khớp với /mystatus)
  • Tên lệnh phải bắt đầu bằng chữ cái và chỉ chứa chữ cái, số, dấu gạch ngang và gạch dưới
  • Tên lệnh dành riêng (như help, status, reset, v.v.) không thể bị plugins ghi đè
  • Đăng ký lệnh trùng lặp giữa các plugins sẽ thất bại với lỗi diagnostic

Đăng ký background services

export default function (api) {
  api.registerService({
    id: "my-service",
    start: () => api.logger.info("ready"),
    stop: () => api.logger.info("bye"),
  });
}

Naming conventions

  • Gateway methods: pluginId.action (ví dụ: voicecall.status)
  • Tools: snake_case (ví dụ: voice_call)
  • CLI commands: kebab hoặc camel, nhưng tránh xung đột với core commands

Skills

Plugins có thể đi kèm skill trong repo (skills/<name>/SKILL.md). Bật nó với plugins.entries.<id>.enabled (hoặc các cổng config khác) và đảm bảo nó có mặt trong workspace/managed skills locations của các bạn.

Distribution (npm)

Packaging được khuyến nghị:

  • Package chính: openclaw (repo này)
  • Plugins: các npm packages riêng dưới @openclaw/* (ví dụ: @openclaw/voice-call)

Publishing contract:

  • package.json của plugin phải bao gồm openclaw.extensions với một hoặc nhiều entry files.
  • Entry files có thể là .js hoặc .ts (jiti tải TS lúc runtime).
  • openclaw plugins install <npm-spec> dùng npm pack, giải nén vào ~/.openclaw/extensions/<id>/, và bật nó trong config.
  • Tính ổn định config key: scoped packages được normalize thành id không có scope cho plugins.entries.*.

Ví dụ plugin: Voice Call

Repo này bao gồm một voice-call plugin (Twilio hoặc log fallback):

  • Source: extensions/voice-call
  • Skill: skills/voice-call
  • CLI: openclaw voicecall start|status
  • Tool: voice_call
  • RPC: voicecall.start, voicecall.status
  • Config (twilio): provider: "twilio" + twilio.accountSid/authToken/from (tùy chọn statusCallbackUrl, twimlUrl)
  • Config (dev): provider: "log" (không có network)

Xem Voice Callextensions/voice-call/README.md để biết cách thiết lập và sử dụng.

Lưu ý bảo mật

Plugins chạy in-process với Gateway. Hãy coi chúng như code đáng tin cậy:

  • Chỉ cài plugins mà các bạn tin tưởng.
  • Ưu tiên dùng allowlists plugins.allow.
  • Khởi động lại Gateway sau khi thay đổi.

Testing plugins

Plugins có thể (và nên) đi kèm tests:

  • In-repo plugins có thể giữ Vitest tests dưới src/** (ví dụ: src/plugins/voice-call.plugin.test.ts).
  • Plugins được publish riêng nên chạy CI riêng (lint/build/test) và xác thực openclaw.extensions trỏ đến built entrypoint (dist/index.js).