Плагины OpenClaw

Обновлено: 2026-04-05

Плагины OpenClaw

OpenClaw имеет расширяемую архитектуру, поддерживающую плагины для добавления новой функциональности, интеграций и кастомизации.

Архитектура плагинов

Типы плагинов

Тип плагина Назначение Примеры
Каналы Добавление поддержки новых мессенджеров Slack, Microsoft Teams, Email
Навыки Расширение возможностей агентов Google Calendar, Jira, Notion
Интеграции Подключение внешних сервисов Stripe, Salesforce, GitHub
UI расширения Дополнительные интерфейсы Custom dashboards, widgets
Мидлвари Обработка запросов/ответов Auth, logging, rate limiting
Провайдеры Альтернативные AI модели Local LLMs, custom APIs

Структура плагина

my-openclaw-plugin/
├── package.json          # Метаданные плагина
├── index.js             # Основной файл плагина
├── config.schema.json   # Схема конфигурации
├── README.md            # Документация
├── tests/               # Тесты
│   └── index.test.js
├── src/                 # Исходный код
│   ├── channels/        # Каналы (опционально)
│   ├── skills/          # Навыки (опционально)
│   └── integrations/    # Интеграции (опционально)
└── examples/            # Примеры использования
    └── config.example.json

Создание плагина

Шаг 1: Инициализация проекта

# Создайте директорию для плагина
mkdir my-openclaw-plugin
cd my-openclaw-plugin

# Инициализируйте package.json
npm init -y

# Установите зависимости для разработки
npm install --save-dev @openclaw/plugin-sdk eslint prettier

Шаг 2: package.json

{
  "name": "openclaw-plugin-myplugin",
  "version": "1.0.0",
  "description": "Мой кастомный плагин для OpenClaw",
  "main": "index.js",
  "type": "module",
  "keywords": ["openclaw", "plugin"],
  "author": "Ваше Имя",
  "license": "MIT",
  "openclaw": {
    "type": "skill",  # channel, skill, integration, middleware, provider
    "version": ">=1.0.0",
    "configSchema": "./config.schema.json"
  },
  "dependencies": {
    "axios": "^1.6.0"
  },
  "devDependencies": {
    "@openclaw/plugin-sdk": "^1.0.0",
    "eslint": "^8.0.0",
    "prettier": "^3.0.0"
  }
}

Шаг 3: Основной файл плагина (index.js)

import { BasePlugin } from '@openclaw/plugin-sdk';

export default class MyPlugin extends BasePlugin {
  constructor(config, context) {
    super(config, context);

    // Инициализация плагина
    this.name = 'My Plugin';
    this.version = '1.0.0';

    // Конфигурация по умолчанию
    this.defaultConfig = {
      apiKey: '',
      endpoint: 'https://api.example.com',
      timeout: 5000
    };
  }

  async initialize() {
    // Инициализация плагина
    this.logger.info(`Initializing ${this.name} v${this.version}`);

    // Проверка конфигурации
    if (!this.config.apiKey) {
      throw new Error('API key is required');
    }

    // Инициализация клиента API
    this.client = new MyAPIClient(this.config);

    this.logger.info(`${this.name} initialized successfully`);
  }

  async execute(action, params) {
    // Обработка действий
    switch (action) {
      case 'get_data':
        return await this.getData(params);
      case 'process_data':
        return await this.processData(params);
      default:
        throw new Error(`Unknown action: ${action}`);
    }
  }

  async getData(params) {
    const { query, limit = 10 } = params;

    try {
      const data = await this.client.search(query, limit);
      return {
        success: true,
        data: data,
        count: data.length
      };
    } catch (error) {
      this.logger.error(`Failed to get data: ${error.message}`);
      return {
        success: false,
        error: error.message
      };
    }
  }

  async processData(params) {
    const { data, operation } = params;

    // Обработка данных
    const result = await this.client.process(data, operation);

    return {
      success: true,
      result: result
    };
  }

  async cleanup() {
    // Очистка ресурсов
    if (this.client) {
      await this.client.disconnect();
    }

    this.logger.info(`${this.name} cleaned up`);
  }

  // Методы для UI (опционально)
  getUIComponents() {
    return {
      dashboard: './src/ui/dashboard.js',
      settings: './src/ui/settings.js'
    };
  }

  // Метрики для мониторинга (опционально)
  getMetrics() {
    return {
      requests_total: this.metrics.requests,
      errors_total: this.metrics.errors,
      response_time_ms: this.metrics.responseTime
    };
  }
}

Шаг 4: Схема конфигурации (config.schema.json)

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "My Plugin Configuration",
  "description": "Конфигурация для моего плагина",
  "type": "object",
  "properties": {
    "apiKey": {
      "type": "string",
      "description": "API ключ для внешнего сервиса",
      "minLength": 1
    },
    "endpoint": {
      "type": "string",
      "description": "URL endpoint API",
      "format": "uri",
      "default": "https://api.example.com"
    },
    "timeout": {
      "type": "integer",
      "description": "Таймаут запросов в миллисекундах",
      "minimum": 1000,
      "maximum": 30000,
      "default": 5000
    },
    "retry": {
      "type": "object",
      "description": "Настройки повторных попыток",
      "properties": {
        "attempts": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5,
          "default": 3
        },
        "delay": {
          "type": "integer",
          "minimum": 100,
          "maximum": 5000,
          "default": 1000
        }
      },
      "default": {
        "attempts": 3,
        "delay": 1000
      }
    },
    "cache": {
      "type": "object",
      "description": "Настройки кэширования",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": true
        },
        "ttl": {
          "type": "integer",
          "description": "Время жизни кэша в секундах",
          "minimum": 60,
          "maximum": 86400,
          "default": 3600
        }
      }
    }
  },
  "required": ["apiKey"],
  "additionalProperties": false
}

Примеры плагинов

Пример 1: Плагин для Google Calendar

import { BasePlugin } from '@openclaw/plugin-sdk';
import { google } from 'googleapis';

export default class GoogleCalendarPlugin extends BasePlugin {
  constructor(config, context) {
    super(config, context);
    this.name = 'Google Calendar';
    this.scopes = ['https://www.googleapis.com/auth/calendar'];
  }

  async initialize() {
    const auth = new google.auth.OAuth2(
      this.config.clientId,
      this.config.clientSecret,
      this.config.redirectUri
    );

    auth.setCredentials({
      access_token: this.config.accessToken,
      refresh_token: this.config.refreshToken
    });

    this.calendar = google.calendar({ version: 'v3', auth });
  }

  async execute(action, params) {
    switch (action) {
      case 'list_events':
        return await this.listEvents(params);
      case 'create_event':
        return await this.createEvent(params);
      case 'update_event':
        return await this.updateEvent(params);
      case 'delete_event':
        return await this.deleteEvent(params);
      default:
        throw new Error(`Unknown action: ${action}`);
    }
  }

  async listEvents({ calendarId = 'primary', maxResults = 10, timeMin, timeMax }) {
    const response = await this.calendar.events.list({
      calendarId,
      maxResults,
      timeMin: timeMin || new Date().toISOString(),
      timeMax,
      singleEvents: true,
      orderBy: 'startTime'
    });

    return response.data.items;
  }

  // ... другие методы
}

Пример 2: Плагин для Jira

import { BasePlugin } from '@openclaw/plugin-sdk';
import JiraClient from 'jira-client';

export default class JiraPlugin extends BasePlugin {
  async initialize() {
    this.jira = new JiraClient({
      protocol: 'https',
      host: this.config.host,
      username: this.config.username,
      password: this.config.apiToken,
      apiVersion: '2',
      strictSSL: true
    });
  }

  async execute(action, params) {
    switch (action) {
      case 'create_issue':
        return await this.createIssue(params);
      case 'search_issues':
        return await this.searchIssues(params);
      case 'add_comment':
        return await this.addComment(params);
      case 'update_status':
        return await this.updateStatus(params);
      default:
        throw new Error(`Unknown action: ${action}`);
    }
  }

  async createIssue({ projectKey, summary, description, issueType = 'Task' }) {
    const issue = {
      fields: {
        project: { key: projectKey },
        summary: summary,
        description: description,
        issuetype: { name: issueType }
      }
    };

    return await this.jira.addNewIssue(issue);
  }

  // ... другие методы
}

Установка и управление плагинами

Установка плагина

# Установка из npm
openclaw plugins install openclaw-plugin-myplugin

# Установка из локального файла
openclaw plugins install ./path/to/my-plugin.tar.gz

# Установка из GitHub
openclaw plugins install github:username/repo

# Установка с конкретной версией
openclaw plugins install openclaw-plugin-myplugin@1.2.3

Управление плагинами

# Список установленных плагинов
openclaw plugins list

# Информация о плагине
openclaw plugins info myplugin

# Включение/выключение плагина
openclaw plugins enable myplugin
openclaw plugins disable myplugin

# Обновление плагина
openclaw plugins update myplugin

# Удаление плагина
openclaw plugins remove myplugin

# Проверка обновлений
openclaw plugins check-updates

Конфигурация плагина

{
  "plugins": {
    "myplugin": {
      "enabled": true,
      "config": {
        "apiKey": "${MYPLUGIN_API_KEY}",
        "endpoint": "https://api.example.com",
        "timeout": 5000
      },
      "permissions": {
        "channels": ["telegram", "discord"],
        "agents": ["personal", "work"],
        "skills": ["read", "write"]
      }
    },

    "google-calendar": {
      "enabled": true,
      "config": {
        "clientId": "${GOOGLE_CLIENT_ID}",
        "clientSecret": "${GOOGLE_CLIENT_SECRET}",
        "accessToken": "${GOOGLE_ACCESS_TOKEN}",
        "refreshToken": "${GOOGLE_REFRESH_TOKEN}"
      }
    }
  }
}

Безопасность плагинов

Политики безопасности

{
  "plugins": {
    "security": {
      "sandbox": {
        "enabled": true,
        "level": "strict",  // strict, moderate, permissive
        "allowedAPIs": ["fs.read", "http.get", "child_process.exec"],
        "deniedAPIs": ["fs.write", "process.exit", "require"]
      },

      "permissions": {
        "requireApproval": true,
        "autoGrant": ["read", "network"],
        "requireManualGrant": ["write", "exec", "config"]
      },

      "codeReview": {
        "enabled": true,
        "requireSignature": true,
        "allowedAuthors": ["openclaw", "trusted-org"],
        "scanForMalware": true
      },

      "updates": {
        "autoUpdate": false,
        "verifySignature": true,
        "allowMajorUpdates": false
      }
    }
  }
}

Аудит плагинов

# Проверка безопасности плагина
openclaw plugins audit myplugin

# Сканирование на уязвимости
openclaw plugins scan-vulnerabilities

# Проверка подписи
openclaw plugins verify-signature myplugin

# Аудит разрешений
openclaw plugins audit-permissions

Разработка и тестирование

Среда разработки

# Создание development environment
openclaw plugins dev-init myplugin

# Запуск плагина в development mode
openclaw plugins dev-run myplugin

# Тестирование плагина
openclaw plugins test myplugin

# Сборка плагина для production
openclaw plugins build myplugin

# Публикация плагина
openclaw plugins publish myplugin --registry npm

Тестирование плагина

// tests/myplugin.test.js
import { testPlugin } from '@openclaw/plugin-sdk/testing';
import MyPlugin from '../index.js';

describe('MyPlugin', () => {
  let plugin;

  beforeEach(async () => {
    plugin = await testPlugin(MyPlugin, {
      apiKey: 'test-key',
      endpoint: 'http://test.endpoint'
    });
  });

  afterEach(async () => {
    await plugin.cleanup();
  });

  test('should initialize successfully', () => {
    expect(plugin.name).toBe('My Plugin');
    expect(plugin.version).toBe('1.0.0');
  });

  test('should get data', async () => {
    const result = await plugin.execute('get_data', {
      query: 'test',
      limit: 5
    });

    expect(result.success).toBe(true);
    expect(result.data).toBeDefined();
  });

  test('should handle errors', async () => {
    // Тестирование обработки ошибок
    const result = await plugin.execute('get_data', {
      query: 'error'
    });

    expect(result.success).toBe(false);
    expect(result.error).toBeDefined();
  });
});

Публикация плагинов

Подготовка к публикации

# Увеличьте версию
npm version patch  # или minor, major

# Создайте архив
npm pack

# Проверьте архив
tar -tzf openclaw-plugin-myplugin-1.0.0.tgz

# Тестирование установки
openclaw plugins install ./openclaw-plugin-myplugin-1.0.0.tgz --test

Публикация в реестр

# Публикация в npm
npm publish --access public

# Публикация в GitHub Packages
npm publish --registry=https://npm.pkg.github.com

# Публикация в приватный реестр
npm publish --registry=https://registry.company.com

Документация плагина

# My Plugin для OpenClaw

## Описание
Мой плагин добавляет интеграцию с [Название сервиса] в OpenClaw.

## Установка
```bash
openclaw plugins install openclaw-plugin-myplugin

Конфигурация

{
  "plugins": {
    "myplugin": {
      "enabled": true,
      "config": {
        "apiKey": "ваш_api_ключ",
        "endpoint": "https://api.example.com"
      }
    }
  }
}

Использование

# Через команды
openclaw myplugin get-data --query "поисковый запрос"

# Через агентов
Агент может использовать плагин через команды:
- "получи данные о ..."
- "обработай эти данные"

API

Действия:

  • get_data - получение данных
  • process_data - обработка данных

Лицензия

MIT

Помогла ли вам эта статья?

Оставьте отзыв или предложите улучшения

🐛 Сообщить об ошибке

Комментарии и обсуждение

Пока нет комментариев. Будьте первым!

Добавить комментарий

Комментарии проходят модерацию