채널 plugin 만들기
이 가이드는 OpenClaw를 메시징 플랫폼에 연결하는 채널 plugin을 만드는 과정을 안내합니다. 끝까지 따라가면 DM 보안, 페어링, 답글 스레딩, 아웃바운드 메시징을 갖춘 동작하는 채널을 만들 수 있습니다.아직 OpenClaw plugin을 한 번도 만들어 본 적이 없다면 먼저
기본 패키지 구조와 manifest 설정을 위해
Getting Started를 읽으세요.
채널 plugin 작동 방식
채널 plugin에는 자체 send/edit/react 도구가 필요하지 않습니다. OpenClaw는 코어에 하나의 공용message 도구를 유지합니다. plugin이 소유하는 것은 다음입니다:
- Config — 계정 해석 및 설정 wizard
- Security — DM 정책 및 allowlist
- Pairing — DM 승인 흐름
- Session grammar — provider별 대화 ID를 기본 채팅, 스레드 ID, 부모 대체 항목에 매핑하는 방식
- Outbound — 플랫폼으로 텍스트, 미디어, 투표를 보내는 기능
- Threading — 답글이 스레드로 연결되는 방식
:thread: bookkeeping, 그리고 dispatch를 소유합니다.
플랫폼이 대화 ID 내부에 추가 범위를 저장한다면, 해당 파싱은
plugin의 messaging.resolveSessionConversation(...)에 유지하세요. 이것이
rawId를 기본 대화 ID, 선택적 스레드 ID, 명시적 baseConversationId,
그리고 모든 parentConversationCandidates에 매핑하는 canonical hook입니다.
parentConversationCandidates를 반환할 때는 가장 좁은 부모에서
가장 넓은/기본 대화 순으로 정렬하세요.
채널 레지스트리가 부팅되기 전에 동일한 파싱이 필요한 번들 plugin은
일치하는 resolveSessionConversation(...) export를 가진 최상위
session-key-api.ts 파일을 노출할 수도 있습니다. 코어는 런타임 plugin 레지스트리를
아직 사용할 수 없을 때만 그 bootstrap-safe 표면을 사용합니다.
messaging.resolveParentConversationCandidates(...)는
plugin이 일반/raw ID 위에 부모 대체 항목만 필요로 할 때 레거시 호환성 대체 경로로 계속 사용할 수 있습니다.
두 hook이 모두 존재하면 코어는 먼저
resolveSessionConversation(...).parentConversationCandidates를 사용하고,
canonical hook이 이를 생략한 경우에만
resolveParentConversationCandidates(...)로 대체합니다.
승인 및 채널 capability
대부분의 채널 plugin은 승인 전용 코드가 필요하지 않습니다.- 코어는 같은 채팅의
/approve, 공용 승인 버튼 payload, 일반적인 대체 전달을 소유합니다. - 채널에 승인별 동작이 필요할 때는 채널 plugin에 하나의
approvalCapability객체를 두는 방식을 선호하세요. approvalCapability.authorizeActorAction과approvalCapability.getActionAvailabilityState는 canonical 승인 인증 seam입니다.- 중복된 로컬 승인 프롬프트 숨기기 또는 전달 전 타이핑 표시기 보내기 같은 채널별 payload 수명 주기 동작에는
outbound.shouldSuppressLocalPayloadPrompt또는outbound.beforeDeliverPayload를 사용하세요. - 네이티브 승인 라우팅 또는 대체 억제에는
approvalCapability.delivery만 사용하세요. - 공용 renderer 대신 채널이 정말로 사용자 지정 승인 payload가 필요할 때만
approvalCapability.render를 사용하세요. - 채널이 기존 config에서 안정적인 owner 유사 DM 신원을 추론할 수 있다면, 승인별 코어 로직을 추가하지 않고도 같은 채팅의
/approve를 제한하기 위해openclaw/plugin-sdk/approval-runtime의createResolvedApproverActionAuthAdapter를 사용하세요. - 채널에 네이티브 승인 전달이 필요하다면 채널 코드는 대상 정규화와 transport hook에만 집중시키세요. 요청 필터링, 라우팅, dedupe, 만료, gateway subscription은 코어가 소유하도록
openclaw/plugin-sdk/approval-runtime의createChannelExecApprovalProfile,createChannelNativeOriginTargetResolver,createChannelApproverDmTargetResolver,createApproverRestrictedNativeApprovalCapability,createChannelNativeApprovalRuntime을 사용하세요. - 네이티브 승인 채널은
accountId와approvalKind를 모두 해당 helper를 통해 라우팅해야 합니다.accountId는 멀티 계정 승인 정책이 올바른 봇 계정 범위에 유지되게 하고,approvalKind는 코어에 하드코딩 분기를 추가하지 않고도 exec 대 plugin 승인 동작을 채널에 제공하게 합니다. - 전달된 승인 ID 종류를 처음부터 끝까지 보존하세요. 네이티브 클라이언트는 exec 대 plugin 승인 라우팅을 채널 로컬 상태에서 추측하거나 다시 쓰면 안 됩니다.
- 서로 다른 승인 종류는 의도적으로 서로 다른 네이티브 표면을 노출할 수 있습니다.
현재 번들 예시:
- Slack은 exec 및 plugin ID 모두에 대해 네이티브 승인 라우팅을 유지합니다.
- Matrix는 exec 승인에만 네이티브 DM/채널 라우팅을 유지하고, plugin 승인은 공용 같은 채팅
/approve경로에 남겨 둡니다.
createApproverRestrictedNativeApprovalAdapter는 여전히 호환성 래퍼로 존재하지만, 새 코드는 capability builder를 선호하고 plugin에approvalCapability를 노출해야 합니다.
openclaw/plugin-sdk/approval-auth-runtimeopenclaw/plugin-sdk/approval-client-runtimeopenclaw/plugin-sdk/approval-delivery-runtimeopenclaw/plugin-sdk/approval-native-runtimeopenclaw/plugin-sdk/approval-reply-runtime
openclaw/plugin-sdk/setup-runtime,
openclaw/plugin-sdk/setup-adapter-runtime,
openclaw/plugin-sdk/reply-runtime,
openclaw/plugin-sdk/reply-dispatch-runtime,
openclaw/plugin-sdk/reply-reference, 그리고
openclaw/plugin-sdk/reply-chunking을 선호하세요.
설정과 관련해서는 특히 다음을 참고하세요:
openclaw/plugin-sdk/setup-runtime은 런타임에 안전한 설정 helper를 다룹니다: import-safe setup patch adapter(createPatchedAccountSetupAdapter,createEnvPatchedAccountSetupAdapter,createSetupInputPresenceValidator), lookup-note 출력,promptResolvedAllowFrom,splitSetupEntries, 그리고 위임된 setup-proxy builderopenclaw/plugin-sdk/setup-adapter-runtime은createEnvPatchedAccountSetupAdapter를 위한 좁은 env 인식 adapter seam입니다openclaw/plugin-sdk/channel-setup은 선택적 설치 setup builder와 몇 가지 setup-safe primitive를 다룹니다:createOptionalChannelSetupSurface,createOptionalChannelSetupAdapter,createOptionalChannelSetupWizard,DEFAULT_ACCOUNT_ID,createTopLevelChannelDmPolicy,setSetupChannelEnabled, 그리고splitSetupEntries- 더 무거운 공용 setup/config helper(예:
moveSingleAccountChannelSectionToDefaultAccount(...))도 필요할 때만 더 넓은openclaw/plugin-sdk/setupseam을 사용하세요
createOptionalChannelSetupSurface(...)를 선호하세요. 생성된
adapter/wizard는 config 쓰기와 finalization에서 fail closed하며,
검증, finalize, docs-link 문구 전반에서 동일한 설치 필요 메시지를 재사용합니다.
다른 핫 채널 경로에서도 더 넓은 레거시 표면보다 좁은 helper를 선호하세요:
- 멀티 계정 config 및 기본 계정 대체에는
openclaw/plugin-sdk/account-core,openclaw/plugin-sdk/account-id,openclaw/plugin-sdk/account-resolution, 그리고openclaw/plugin-sdk/account-helpers - 인바운드 route/envelope 및 record-and-dispatch 연결에는
openclaw/plugin-sdk/inbound-envelope와openclaw/plugin-sdk/inbound-reply-dispatch - 대상 파싱/매칭에는
openclaw/plugin-sdk/messaging-targets - 미디어 로딩과 아웃바운드
identity/send delegate에는
openclaw/plugin-sdk/outbound-media와openclaw/plugin-sdk/outbound-runtime - thread-binding 수명 주기
및 adapter 등록에는
openclaw/plugin-sdk/thread-bindings-runtime - 레거시 agent/media
payload 필드 레이아웃이 여전히 필요할 때만
openclaw/plugin-sdk/agent-media-payload - Telegram 사용자 지정 명령
정규화, 중복/충돌 검증, 대체 안정적 명령
config 계약에는
openclaw/plugin-sdk/telegram-command-config
단계별 안내
패키지와 manifest
표준 plugin 파일을 만드세요.
package.json의 channel 필드는
이것이 채널 plugin임을 나타냅니다. 전체 패키지 메타데이터 표면은
Plugin Setup and Config를 참조하세요:채널 plugin 객체 만들기
ChannelPlugin 인터페이스에는 많은 선택적 adapter 표면이 있습니다. 최소 항목인
id와 setup부터 시작하고 필요에 따라 adapter를 추가하세요.src/channel.ts를 만드세요:src/channel.ts
createChatChannelPlugin이 대신 처리해 주는 것
createChatChannelPlugin이 대신 처리해 주는 것
저수준 adapter 인터페이스를 수동으로 구현하는 대신 선언적 옵션을 전달하면
builder가 이를 조합해 줍니다:
완전한 제어가 필요하다면 선언적 옵션 대신 원시 adapter 객체를 직접 전달할 수도 있습니다.
| 옵션 | 연결되는 항목 |
|---|---|
security.dm | config 필드에서 범위가 지정된 DM 보안 해석기 |
pairing.text | 코드 교환이 있는 텍스트 기반 DM 페어링 흐름 |
threading | reply-to-mode 해석기(고정, 계정 범위, 또는 사용자 지정) |
outbound.attachedResults | 결과 메타데이터(메시지 ID)를 반환하는 send 함수 |
entry point 연결
index.ts를 만드세요:index.ts
registerCliMetadata(...)에 넣어
OpenClaw가 전체 채널 런타임을 활성화하지 않고도 루트 도움말에 이를 표시할 수 있게 하세요.
일반 전체 로드에서도 동일한 descriptor가 실제 명령 등록에 사용됩니다.
registerFull(...)은 런타임 전용 작업에 유지하세요.
registerFull(...)이 gateway RPC 메서드를 등록한다면
plugin 전용 prefix를 사용하세요. 코어 관리자 namespace(config.*,
exec.approvals.*, wizard.*, update.*)는 예약되어 있으며 항상
operator.admin으로 해석됩니다.
defineChannelPluginEntry는 등록 모드 분리를 자동으로 처리합니다. 모든
옵션은 Entry Points를 참조하세요.setup entry 추가
온보딩 중 경량 로딩을 위해 OpenClaw는 채널이 비활성화되었거나 구성되지 않은 경우 전체 entry 대신 이를 로드합니다.
이렇게 하면 setup 흐름 중 무거운 런타임 코드를 끌어오지 않아도 됩니다.
자세한 내용은 Setup and Config를 참조하세요.
setup-entry.ts를 만드세요:setup-entry.ts
인바운드 메시지 처리
plugin은 플랫폼에서 메시지를 수신해 OpenClaw로 전달해야 합니다.
일반적인 패턴은 요청을 검증한 뒤 채널의 인바운드 handler를 통해
dispatch하는 webhook입니다:
인바운드 메시지 처리는 채널별입니다. 각 채널 plugin이
자체 인바운드 파이프라인을 소유합니다. 실제 패턴은 번들 채널 plugin
(예: Microsoft Teams 또는 Google Chat plugin 패키지)을 참고하세요.
테스트
파일 구조
고급 주제
스레딩 옵션
고정, 계정 범위, 또는 사용자 지정 reply mode
Message 도구 통합
describeMessageTool 및 action discovery
대상 해석
inferTargetChatType, looksLikeId, resolveTarget
런타임 helper
api.runtime를 통한 TTS, STT, 미디어, 하위 에이전트
일부 번들 helper seam은 번들 plugin 유지 관리와
호환성을 위해 여전히 존재합니다. 하지만 새 채널 plugin에 권장되는 패턴은 아닙니다.
해당 번들 plugin 계열을 직접 유지 관리하는 경우가 아니라면
공용 SDK 표면의 일반적인 channel/setup/reply/runtime subpath를 선호하세요.
다음 단계
- Provider Plugins — plugin이 모델도 제공하는 경우
- SDK Overview — 전체 subpath import 참조
- SDK Testing — 테스트 유틸리티 및 계약 테스트
- Plugin Manifest — 전체 manifest schema