OpenClaw 플러그인으로 기능 확장하기
개발을 하다 보면 기본 기능만으로는 부족할 때가 있죠. 그렇다고 모든 기능을 메인 코드에 다 넣자니 앱이 너무 무거워질까 봐 걱정되기도 하고요. 이럴 때 필요한 기능만 골라 추가하거나, 나중에 선택적으로 사용할 기능을 따로 분리하고 싶을 때 플러그인이 정말 유용해요.
OpenClaw 플러그인은 핵심 기능을 건드리지 않으면서도 새로운 명령어(commands), 도구(tools), Gateway RPC 등을 추가할 수 있는 작은 코드 모듈이에요.
필요한 것
섹션 제목: “필요한 것”- OpenClaw 설치 완료
- TypeScript에 대한 기초 지식 (플러그인은 TypeScript 모듈로 작성됩니다)
- 플러그인 설정을 위한 JSON Schema 이해
빠른 시작
섹션 제목: “빠른 시작”5분 안에 플러그인을 설치하고 확인하는 방법이에요.
- 현재 로드된 플러그인 목록을 확인하세요.
openclaw plugins list- 공식 플러그인을 설치하세요. (예시: Voice Call)
openclaw plugins install @openclaw/voice-call- Gateway를 다시 시작한 다음,
plugins.entries.<id>.config경로에서 설정을 진행하세요.
더 구체적인 예시는 Voice Call 문서에서 볼 수 있어요.
주요 특징 및 공식 플러그인
섹션 제목: “주요 특징 및 공식 플러그인”OpenClaw 플러그인은 실행 시점에 jiti를 통해 로드되는 TypeScript 모듈이에요. 설정 검증 시에는 플러그인 코드를 직접 실행하지 않고, 플러그인 manifest와 JSON Schema를 사용해서 안전해요.
플러그인이 등록할 수 있는 기능들은 다음과 같아요:
- Gateway RPC 메서드 및 HTTP 핸들러
- Agent 도구 및 CLI 명령어
- 백그라운드 서비스
- 스킬(Skills) 및 자동 응답 명령어 (AI Agent를 호출하지 않고 실행)
현재 사용 가능한 공식 플러그인:
- Microsoft Teams: 2026.1.15 버전부터 플러그인으로만 제공돼요.
@openclaw/msteams를 설치해서 사용하세요. - Memory (Core): 기본으로 포함된 메모리 검색 플러그인이에요.
- Memory (LanceDB): 장기 기억을 위한 플러그인으로,
plugins.slots.memory = "memory-lancedb"설정을 통해 사용할 수 있어요. - OAuth 인증 도구: Google Antigravity, Gemini CLI, Qwen 등을 위한 인증 플러그인이 내장되어 있어요 (기본은 비활성 상태).
- Copilot Proxy: 로컬 VS Code Copilot Proxy 브릿지 기능을 제공해요.
플러그인은 Gateway와 동일한 프로세스 내에서 실행되기 때문에, 신뢰할 수 있는 코드만 사용해야 한다는 점을 기억해 주세요.
Runtime Helpers
섹션 제목: “Runtime Helpers”플러그인 내부에서는 api.runtime을 통해 핵심 헬퍼 기능을 사용할 수 있어요. 예를 들어 전화 통신용 TTS(Telephony TTS)를 사용하는 코드는 다음과 같아요.
const result = await api.runtime.tts.textToSpeechTelephony({ text: "Hello from OpenClaw", cfg: api.config,});이 기능은 messages.tts 설정(OpenAI 또는 ElevenLabs)을 그대로 따르며, PCM 오디오 버퍼와 샘플 레이트를 반환해요.
문제 해결
섹션 제목: “문제 해결”플러그인 사용 중 발생할 수 있는 상황이에요.
- 전화 통신에서 Edge TTS 사용 불가: Telephony TTS 기능은 Edge TTS를 지원하지 않아요.
- 오디오 포맷 문제:
api.runtime.tts는 PCM 버퍼를 반환하므로, 각 서비스 제공업체에 맞는 포맷으로 다시 인코딩하거나 리샘플링하는 과정이 필요할 수 있어요.
설정이나 설치 과정에서 도움이 필요하다면 AI Setup Assistant를 활용해 보세요.
다음 단계
섹션 제목: “다음 단계”- Plugin manifest: 플러그인 구조 자세히 보기
- Plugin agent tools: 도구 제작 가이드
- Voice Call: 음성 통화 플러그인 설정
- Matrix: Matrix 채널 연결하기
새로운 기능을 추가하려고 플러그인을 만들었는데, 왜 내가 수정한 코드가 반영되지 않는지 답답했던 적이 있나요? 여러 경로에 플러그인이 섞여 있으면 어떤 설정이 우선적으로 적용되는지 파악하기 어렵죠. OpenClaw가 플러그인을 찾는 명확한 규칙을 알면 이런 문제를 쉽게 해결할 수 있어요.
What You’ll Need
섹션 제목: “What You’ll Need”- OpenClaw 설치 환경
- 플러그인 루트 디렉토리에 포함된
openclaw.plugin.json파일 - (선택 사항)
package.json및 Node.js 패키지 매니저 (npm,pnpm)
Quick Start
섹션 제목: “Quick Start”OpenClaw는 플러그인을 찾을 때 다음 순서대로 스캔을 진행해요. 이 순서는 우선순위이기도 해서, 먼저 발견된 플러그인이 동일한 ID를 가진 다른 플러그인을 무시하고 적용돼요.
- Config paths:
plugins.load.paths에 설정된 파일이나 디렉토리 - Workspace extensions:
<workspace>/.openclaw/extensions/*.ts<workspace>/.openclaw/extensions/*/index.ts
- Global extensions:
~/.openclaw/extensions/*.ts~/.openclaw/extensions/*/index.ts
- Bundled extensions: OpenClaw에 내장된 확장 (기본적으로 비활성화 상태)
<openclaw>/extensions/*
내장(Bundled) 플러그인은 openclaw plugins enable <id> 명령어를 사용하거나 plugins.entries.<id>.enabled 설정을 통해 직접 활성화해야 해요. 반면, 사용자가 직접 설치한 플러그인은 기본적으로 활성화되어 있어요.
Package packs 구성하기
섹션 제목: “Package packs 구성하기”플러그인 디렉토리에 package.json을 만들고 openclaw.extensions 필드를 추가하면 여러 개의 확장을 하나의 팩으로 묶을 수 있어요.
{ "name": "my-pack", "openclaw": { "extensions": ["./src/safety.ts", "./src/tools.ts"] }}이렇게 설정하면 각 항목이 개별 플러그인이 되며, ID는 name/fileBase 형식(예: my-pack/safety)으로 생성돼요. 외부 npm 의존성이 필요하다면 해당 디렉토리에서 npm install이나 pnpm install을 실행해 node_modules를 준비해 주세요.
Channel catalog 메타데이터
섹션 제목: “Channel catalog 메타데이터”채널 플러그인은 openclaw.channel과 openclaw.install 설정을 통해 온보딩 및 설치 힌트 정보를 제공할 수 있어요.
{ "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" } }}또한, 외부 채널 카탈로그(예: MPM 레지스트리 엑스포트)를 JSON 파일 형태로 다음 경로에 두어 병합할 수 있어요.
~/.openclaw/mpm/plugins.json~/.openclaw/mpm/catalog.json~/.openclaw/plugins/catalog.json
또는 OPENCLAW_PLUGIN_CATALOG_PATHS 환경 변수에 JSON 파일 경로를 지정할 수도 있어요.
Troubleshooting
섹션 제목: “Troubleshooting”- 플러그인이 인식되지 않아요: 플러그인 루트 디렉토리에
openclaw.plugin.json매니페스트 파일이 있는지 확인해 보세요. 파일 경로를 직접 가리키는 경우에도 해당 파일이 있는 디렉토리에 매니페스트가 있어야 해요. - 내장 플러그인이 작동하지 않아요: Bundled 플러그인은 기본적으로 비활성 상태예요.
openclaw plugins enable <id>명령어로 활성화했는지 확인해 주세요. - 동일한 ID의 플러그인이 여러 개 있어요: OpenClaw는 검색 순서에서 가장 먼저 발견된 것을 사용하고 나머지는 무시해요. 우선순위가 높은 경로(Config paths나 Workspace)를 확인해 보세요.
더 자세한 설정 방법이나 도움이 필요하다면 AI Setup Assistant에게 물어보세요!
What’s Next
섹션 제목: “What’s Next”새로운 도구를 도입할 때 플러그인 설정이 꼬여서 고생해 본 적 있으시죠? 내가 설치한 플러그인의 ID가 정확히 무엇인지, 설정값은 어디에 넣어야 하는지 몰라 헤매는 상황은 개발자라면 누구나 겪는 통증입니다. OpenClaw는 이런 혼란을 줄이기 위해 명확한 규칙을 가지고 있습니다.
플러그인 시스템을 제대로 이해하고 나면, 복잡한 기능 확장도 훨씬 수월해질 거예요. OpenClaw 플러그인의 핵심 메커니즘을 하나씩 살펴볼까요?
필요한 것
섹션 제목: “필요한 것”시작하기 전에 다음 항목이 준비되어 있는지 확인해 주세요.
- OpenClaw 설치 완료
- 플러그인 manifest (
openclaw.plugin.json) 및package.json에 대한 기본 지식
빠른 시작
섹션 제목: “빠른 시작”OpenClaw 플러그인을 빠르게 설정하고 사용하는 방법입니다.
1. Plugin ID 확인하기
섹션 제목: “1. Plugin ID 확인하기”플러그인 ID는 다음 규칙에 따라 자동으로 결정됩니다.
- Package packs:
package.json의name필드를 사용해요. - Standalone file: 파일의 이름이 ID가 됩니다. (예:
~/.../voice-call.ts→voice-call)
만약 플러그인 내부에서 id를 직접 export하면 OpenClaw는 그 값을 사용해요. 다만, 설정된 ID와 일치하지 않으면 경고가 발생할 수 있습니다.
2. 기본 Config 설정
섹션 제목: “2. 기본 Config 설정”openclaw.config.json5 파일에서 플러그인을 활성화하고 관리할 수 있습니다.
{ plugins: { enabled: true, allow: ["voice-call"], deny: ["untrusted-plugin"], load: { paths: ["~/Projects/oss/voice-call-extension"] }, entries: { "voice-call": { enabled: true, config: { provider: "twilio" } }, }, },}enabled: 전체 플러그인 시스템의 마스터 스위치입니다. (기본값: true)allow/deny: 허용 리스트와 차단 리스트입니다.deny가 우선순위가 높아요.load.paths: 추가로 플러그인 파일이나 디렉토리를 불러올 경로를 지정합니다.entries.<id>: 개별 플러그인의 활성화 여부와 상세 설정을 관리합니다.
주의: 설정을 변경한 후에는 반드시 Gateway를 재시작해야 적용됩니다.
Plugin Slots (독점 카테고리)
섹션 제목: “Plugin Slots (독점 카테고리)”어떤 플러그인들은 같은 카테고리 내에서 단 하나만 활성화되어야 합니다. 이때 plugins.slots를 사용해 어떤 플러그인이 해당 슬롯을 차지할지 선택합니다.
{ plugins: { slots: { memory: "memory-core", // memory 플러그인을 비활성화하려면 "none" 입력 }, },}만약 여러 플러그인이 kind: "memory"를 선언하더라도, 선택된 하나만 로드됩니다. 나머지는 비활성화되며 진단 메시지가 표시됩니다.
Control UI 설정
섹션 제목: “Control UI 설정”Control UI는 config.schema를 사용해 더 나은 폼 화면을 렌더링합니다. uiHints를 사용하면 레이블을 붙이거나 비밀 정보를 숨길 수 있습니다.
{ "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 명령어 활용하기
섹션 제목: “CLI 명령어 활용하기”터미널에서 다음 명령어들로 플러그인을 직접 제어할 수 있습니다.
openclaw plugins listopenclaw plugins info <id>openclaw plugins install <path> # 로컬 파일/디렉토리를 ~/.openclaw/extensions/<id>로 복사openclaw plugins install ./extensions/voice-call # 상대 경로 가능openclaw plugins install ./plugin.tgz # 로컬 tarball에서 설치openclaw plugins install ./plugin.zip # 로컬 zip에서 설치openclaw plugins install -l ./extensions/voice-call # 개발용 링크 (복사 안 함)openclaw plugins install @openclaw/voice-call # npm에서 설치openclaw plugins update <id>openclaw plugins update --allopenclaw plugins enable <id>openclaw plugins disable <id>openclaw plugins doctorplugins update는 plugins.installs 아래에서 관리되는 npm 설치 건에 대해서만 작동합니다.
Plugin API 및 Hooks
섹션 제목: “Plugin API 및 Hooks”플러그인은 함수 형태나 객체 형태로 export할 수 있습니다.
- 함수형:
(api) => { ... } - 객체형:
{ id, name, configSchema, register(api) { ... } }
또한 플러그인 내부에 Hook을 포함시켜 런타임에 등록할 수 있습니다. 별도의 Hook 팩 설치 없이도 이벤트 기반 자동화 기능을 묶어서 제공할 수 있죠.
import { registerPluginHooksFromDir } from "openclaw/plugin-sdk";
export default function register(api) { registerPluginHooksFromDir(api, "./hooks");}- 플러그인이 관리하는 Hook은
openclaw hooks list에서plugin:<id>라는 이름으로 표시됩니다. - 이 Hook들은
openclaw hooks명령어로 개별 제어할 수 없으며, 플러그인 자체를 활성화/비활성화해야 합니다.
문제 해결
섹션 제목: “문제 해결”문제가 발생했을 때 다음 내용을 확인해 보세요.
- Unknown plugin id:
entries,allow,deny,slots에 정의되지 않은 ID를 적으면 에러가 발생합니다. - Validation Error: 플러그인 설정은
openclaw.plugin.json에 포함된 JSON Schema(configSchema)를 기준으로 엄격하게 검사됩니다. - 비활성화된 플러그인 경고: 플러그인이 비활성화되어 있어도 설정값은 유지되지만, 관련 경고가 표시될 수 있습니다.
- 채널 에러:
channels.<id>키가 알 수 없는 값일 경우 에러가 발생합니다. 단, 플러그인 manifest에서 해당 채널 ID를 선언했다면 괜찮습니다.
궁금한 점이 더 있나요? AI Setup Assistant에게 질문해 보세요!
다음 단계
섹션 제목: “다음 단계”새로운 모델이나 메시징 플랫폼을 프로젝트에 연결할 때마다 매번 외부 스크립트를 짜거나 복잡한 인증 과정을 수동으로 처리하느라 고생하신 적 있으시죠? 설정 파일은 점점 복잡해지고, CLI에서 바로 인증을 처리할 수 없어서 개발 흐름이 툭툭 끊기는 경험은 개발자라면 누구나 겪는 고민이에요.
OpenClaw의 플러그인 시스템을 사용하면 이런 번거로운 과정들을 깔끔하게 자동화할 수 있어요. 외부 스크립트 없이도 OpenClaw 내부에서 OAuth나 API key 설정을 직접 실행할 수 있도록 만드는 방법을 지금부터 소개해 드릴게요.
필요한 것
섹션 제목: “필요한 것”시작하기 전에 다음 항목들이 준비되었는지 확인해 주세요.
- OpenClaw 환경
- TypeScript 및 Node.js 기본 지식
빠른 시작
섹션 제목: “빠른 시작”api.registerProvider(...)를 사용하면 모델 Provider의 인증 flow를 등록할 수 있어요. 등록된 인증 방식은 openclaw models auth login 명령어를 통해 CLI에서 바로 호출할 수 있습니다.
api.registerProvider({ id: "acme", label: "AcmeAI", auth: [ { id: "oauth", label: "OAuth", kind: "oauth", run: async (ctx) => { // OAuth flow를 실행하고 auth profiles를 반환합니다. return { profiles: [ { profileId: "acme:default", credential: { type: "oauth", provider: "acme", access: "...", refresh: "...", expires: Date.now() + 3600 * 1000, }, }, ], defaultModel: "acme/opus-1", }; }, }, ],});참고 사항:
run함수는prompter,runtime,openUrl,oauth.createVpsAwareHandlers헬퍼가 포함된ProviderAuthContext를 전달받아요.- 기본 모델이나 Provider 설정을 추가해야 할 때는
configPatch를 반환하세요. defaultModel을 반환하면--set-default플래그를 통해 Agent의 기본값을 업데이트할 수 있어요.
메시징 채널 등록하기
섹션 제목: “메시징 채널 등록하기”WhatsApp이나 Telegram 같은 built-in 채널처럼 동작하는 Channel Plugin을 등록할 수도 있어요. 채널 설정은 channels.<id> 아래에 위치하며 플러그인 코드에 의해 검증됩니다.
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 });}참고 사항:
- 설정값은
plugins.entries가 아닌channels.<id>아래에 두어야 해요. meta.label은 CLI나 UI 리스트에서 라벨로 사용됩니다.meta.aliases를 추가하면 CLI 입력 시 대체 ID를 사용할 수 있어요.meta.preferOver를 통해 특정 채널이 구성되었을 때 자동 활성화를 건너뛸 채널 ID 목록을 지정할 수 있습니다.
새로운 메시징 채널 작성 단계
섹션 제목: “새로운 메시징 채널 작성 단계”모델 Provider가 아닌 새로운 채팅 접점(Messaging Channel)을 만들고 싶다면 다음 단계를 따르세요.
- ID 및 Config 구조 선택: 모든 채널 설정은
channels.<id>아래에 위치해야 해요. 다중 계정 설정이라면channels.<id>.accounts.<accountId>구조를 권장합니다. - 채널 메타데이터 정의:
meta.label,meta.docsPath,meta.blurb등으로 CLI/UI에 표시될 정보를 제어하세요. - 필수 어댑터 구현:
config.listAccountIds,config.resolveAccount,capabilities,outbound.deliveryMode,outbound.sendText를 구현해야 해요. - 선택적 어댑터 추가: 필요에 따라
setup(마법사),security(DM 정책),status,gateway(start/stop),streaming등을 추가할 수 있습니다. - 플러그인 등록:
api.registerChannel({ plugin })으로 마무리하세요.
최소 구성 예시
섹션 제목: “최소 구성 예시”{ channels: { acmechat: { accounts: { default: { token: "ACME_TOKEN", enabled: true }, }, }, },}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 }) => { // 여기에 채널로 text를 전달하는 로직을 작성하세요. return { ok: true }; }, },};
export default function (api) { api.registerChannel({ plugin });}기타 기능 등록하기
섹션 제목: “기타 기능 등록하기”Gateway RPC 메서드
섹션 제목: “Gateway RPC 메서드”Gateway에서 사용할 RPC 메서드를 등록할 수 있습니다.
export default function (api) { api.registerGatewayMethod("myplugin.status", ({ respond }) => { respond(true, { ok: true }); });}CLI 명령어
섹션 제목: “CLI 명령어”커스텀 CLI 명령어를 추가할 수 있습니다.
export default function (api) { api.registerCli( ({ program }) => { program.command("mycmd").action(() => { console.log("Hello"); }); }, { commands: ["mycmd"] }, );}자동 응답 명령어 (Slash Commands)
섹션 제목: “자동 응답 명령어 (Slash Commands)”AI Agent를 거치지 않고 즉시 실행되는 슬래시 명령어를 등록할 수 있어요. 상태 확인이나 설정 변경에 유용합니다.
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}` }; },});커맨드 주요 특징:
- AI Agent보다 먼저 처리됩니다.
- 대소문자를 구분하지 않으며 (
/MyStatus와/mystatus동일) 모든 채널에서 전역적으로 작동해요. senderId,channel,isAuthorizedSender,args,config등의 context를 사용할 수 있습니다.
백그라운드 서비스
섹션 제목: “백그라운드 서비스”플러그인과 함께 실행될 백그라운드 서비스를 등록합니다.
export default function (api) { api.registerService({ id: "my-service", start: () => api.logger.info("ready"), stop: () => api.logger.info("bye"), });}문제 해결
섹션 제목: “문제 해결”- 명령어 중복: 여러 플러그인에서 동일한 이름의 명령어를 등록하려고 하면 진단 에러(diagnostic error)가 발생하며 실패하게 됩니다.
- 예약어 제한:
help,status,reset같은 OpenClaw 예약어는 플러그인에서 오버라이드할 수 없으니 주의해 주세요. - 인자 처리:
acceptsArgs가false인데 인자가 전달되면, 해당 명령어는 매칭되지 않고 다른 핸들러로 넘어갑니다.
도움이 필요하신가요? AI Setup Assistant에게 물어보세요!
What’s Next:
- Plugin agent tools 학습하기
---title: "Naming conventions 및 플러그인 가이드"description: "openclaw 플러그인 개발을 위한 네이밍 규칙, 배포 방법 및 보안 가이드"---
새로운 기능을 추가할 때마다 이름은 어떻게 지을지, 파일 구조는 어떻게 잡을지 고민되시죠? 일관성 없는 네이밍은 나중에 디버깅을 어렵게 만들고 협업 효율을 떨어뜨립니다. openclaw에서 플러그인을 만들 때 서로 약속한 규칙들을 지키면 코드를 훨씬 깔끔하게 관리할 수 있어요.
플러그인 시스템을 제대로 활용하기 위해 꼭 알아야 할 핵심 규칙과 설정 방법들을 정리해 드릴게요.
## 필요한 것
- `openclaw` 메인 패키지- `npm`- `jiti` (런타임에서 TypeScript를 로드할 경우 필요)
## 빠른 시작
5분 만에 플러그인 설정을 시작하는 방법입니다.
1. **네이밍 규칙 준수**: 아래 규칙에 맞춰 이름을 정하세요. - Gateway methods: `pluginId.action` (예: `voicecall.status`) - Tools: `snake_case` (예: `voice_call`) - CLI commands: kebab 또는 camel 케이스 사용 (코어 명령어와 충돌 주의)2. **package.json 설정**: 플러그인 패키지의 `package.json`에 `openclaw.extensions`를 추가하고 엔트리 파일(.js 또는 .ts)을 지정하세요.3. **플러그인 설치**: CLI에서 다음 명령어를 실행하세요. ```bash openclaw plugins install \<npm-spec\>- 활성화: 설정 파일에서
plugins.entries.<id>.enabled를true로 변경하세요.
Skills
섹션 제목: “Skills”플러그인은 저장소 내에 skill을 포함해서 배포할 수 있습니다. skills/<name>/SKILL.md 경로에 파일을 두면 돼요. 해당 기능을 사용하려면 plugins.entries.<id>.enabled와 같은 설정 게이트를 통해 활성화하고, 해당 파일이 workspace나 관리되는 skills 위치에 있는지 확인하세요.
Distribution (npm)
섹션 제목: “Distribution (npm)”플러그인 배포 시 권장하는 패키징 방식입니다.
- 메인 패키지:
openclaw - 플러그인:
@openclaw/*네임스페이스를 사용하는 개별 npm 패키지 (예:@openclaw/voice-call)
배포 규약
섹션 제목: “배포 규약”- 플러그인
package.json에는 하나 이상의 엔트리 파일을 포함한openclaw.extensions필드가 반드시 있어야 합니다. - 엔트리 파일은
.js또는.ts모두 가능합니다. openclaw plugins install <npm-spec>명령어는npm pack을 사용하여 패키지를 추출하고,~/.openclaw/extensions/<id>/경로에 설치한 뒤 설정을 활성화합니다.- 설정 키 안정성: Scoped 패키지(예:
@openclaw/plugin)는 설정 내plugins.entries.*에서 unscoped ID(예:plugin)로 정규화되어 사용됩니다.
Example plugin: Voice Call
섹션 제목: “Example plugin: Voice Call”이 저장소에 포함된 voice-call 플러그인(Twilio 또는 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,twilio.authToken,twilio.from설정 (선택 사항:statusCallbackUrl,twimlUrl) - Config (dev):
provider: "log"(네트워크 연결 없이 로그만 남김)
더 자세한 내용은 Voice Call 문서와 extensions/voice-call/README.md를 참고하세요.
Safety notes
섹션 제목: “Safety notes”플러그인은 Gateway와 동일한 프로세스 내에서 실행됩니다. 따라서 플러그인을 신뢰할 수 있는 코드로 취급해야 합니다.
- 신뢰할 수 있는 플러그인만 설치하세요.
plugins.allow화이트리스트 기능을 사용하는 것이 좋습니다.- 플러그인 설정이나 코드를 변경한 후에는 Gateway를 재시작하세요.
Testing plugins
섹션 제목: “Testing plugins”플러그인 제작 시 테스트 코드를 함께 포함하는 것을 권장합니다.
- 저장소 내 플러그인:
src/**경로 아래에 Vitest 테스트를 작성하세요 (예:src/plugins/voice-call.plugin.test.ts). - 별도 배포 플러그인: 자체 CI(lint/build/test)를 운영하고,
openclaw.extensions가 빌드된 결과물인 엔트리포인트(dist/index.js)를 정확히 가리키고 있는지 확인하세요.
더 궁금한 점이 있다면 AI Setup Assistant에게 물어보세요.
다음 단계
섹션 제목: “다음 단계”OpenClaw Expert
아직 막혀 있나요?
이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.