채널 Plugin 구축
이 가이드는 OpenClaw를 메시징 플랫폼에 연결하는 채널 plugin을 구축하는 과정을 안내합니다. 이 가이드를 마치면 DM 보안, 페어링, 답장 스레딩, 아웃바운드 메시징이 작동하는 채널을 갖추게 됩니다.아직 OpenClaw plugin을 한 번도 만들어본 적이 없다면 먼저
기본 패키지 구조와 manifest 설정을 위해
시작하기를 읽으세요.
채널 plugin의 작동 방식
채널 plugin은 자체 send/edit/react 도구가 필요하지 않습니다. OpenClaw는 코어에 하나의 공유message 도구를 유지합니다. plugin이 담당하는 영역은 다음과 같습니다:
- 설정 — 계정 해석 및 설정 wizard
- 보안 — DM 정책 및 허용 목록
- 페어링 — DM 승인 흐름
- 세션 문법 — provider별 대화 id가 기본 채팅, 스레드 id, 부모 대체 경로에 어떻게 매핑되는지
- 아웃바운드 — 플랫폼으로 텍스트, 미디어, 투표를 보내기
- 스레딩 — 답장을 어떻게 스레드로 연결할지
:thread: 기록 관리, 그리고 디스패치를 담당합니다.
플랫폼이 대화 id 안에 추가 범위를 저장한다면, 그 파싱은
plugin에서 messaging.resolveSessionConversation(...)으로 유지하세요. 이것이 rawId를
기본 대화 id, 선택적 스레드 id, 명시적 baseConversationId,
그리고 모든 parentConversationCandidates로 매핑하는 정식 훅입니다.
parentConversationCandidates를 반환할 때는 가장 좁은 부모부터
가장 넓은/기본 대화 순으로 정렬해 두세요.
채널 레지스트리가 부팅되기 전에 같은 파싱이 필요한 번들 plugin은
일치하는 resolveSessionConversation(...) export를 가진 최상위
session-key-api.ts 파일도 노출할 수 있습니다. 코어는 런타임 plugin 레지스트리를
아직 사용할 수 없을 때만 이 부트스트랩 안전 표면을 사용합니다.
messaging.resolveParentConversationCandidates(...)는 plugin이
일반/raw id 위에 부모 대체 경로만 필요로 할 때를 위한 레거시 호환성 대체 수단으로
여전히 사용할 수 있습니다. 두 훅이 모두 존재하면 코어는 먼저
resolveSessionConversation(...).parentConversationCandidates를 사용하고,
정식 훅이 이를 생략할 때만 resolveParentConversationCandidates(...)로 대체합니다.
승인 및 채널 기능
대부분의 채널 plugin은 승인 전용 코드가 필요하지 않습니다.- 코어는 동일 채팅의
/approve, 공유 승인 버튼 페이로드, 일반적인 대체 전달을 담당합니다. - 채널에 승인 전용 동작이 필요할 때는 채널 plugin에 하나의
approvalCapability객체를 두는 방식을 선호하세요. ChannelPlugin.approvals는 제거되었습니다. 승인 전달/네이티브/렌더링/인증 관련 정보는approvalCapability에 두세요.plugin.auth는 login/logout 전용입니다. 코어는 더 이상 그 객체에서 승인 인증 훅을 읽지 않습니다.approvalCapability.authorizeActorAction과approvalCapability.getActionAvailabilityState가 정식 승인 인증 연결 지점입니다.- 동일 채팅 승인 인증 가용성에는
approvalCapability.getActionAvailabilityState를 사용하세요. - 채널이 네이티브 exec 승인을 노출한다면, 동일 채팅 승인 인증과 다를 때 시작 표면/네이티브 클라이언트 상태를 위해
approvalCapability.getExecInitiatingSurfaceState를 사용하세요. 코어는 이 exec 전용 훅으로enabled와disabled를 구분하고, 시작 채널이 네이티브 exec 승인을 지원하는지 판단하며, 네이티브 클라이언트 대체 안내에 해당 채널을 포함합니다. 일반적인 경우에는createApproverRestrictedNativeApprovalCapability(...)가 이를 채워 줍니다. - 중복된 로컬 승인 프롬프트 숨기기나 전달 전 타이핑 표시 보내기 같은 채널 전용 페이로드 수명 주기 동작에는
outbound.shouldSuppressLocalPayloadPrompt또는outbound.beforeDeliverPayload를 사용하세요. approvalCapability.delivery는 네이티브 승인 라우팅 또는 대체 억제에만 사용하세요.- 채널 소유 네이티브 승인 관련 정보에는
approvalCapability.nativeRuntime를 사용하세요. 핫 채널 엔트리포인트에서는createLazyChannelApprovalNativeRuntimeAdapter(...)로 이를 지연 로드 상태로 유지하세요. 그러면 코어가 승인 수명 주기를 조립할 수 있으면서도 필요 시 런타임 모듈을 가져올 수 있습니다. - 채널이 공유 렌더러 대신 진짜로 커스텀 승인 페이로드가 필요할 때만
approvalCapability.render를 사용하세요. - 채널이 비활성 경로 응답에서 네이티브 exec 승인을 활성화하는 데 필요한 정확한 설정 키를 설명하고 싶다면
approvalCapability.describeExecApprovalSetup을 사용하세요. 이 훅은{ channel, channelLabel, accountId }를 받습니다. 이름 있는 계정 채널은 최상위 기본값 대신channels.<channel>.accounts.<id>.execApprovals.*같은 계정 범위 경로를 렌더링해야 합니다. - 채널이 기존 설정에서 안정적인 소유자형 DM 정체성을 추론할 수 있다면, 승인 전용 코어 로직을 추가하지 말고
openclaw/plugin-sdk/approval-runtime의createResolvedApproverActionAuthAdapter를 사용해 동일 채팅/approve를 제한하세요. - 채널에 네이티브 승인 전달이 필요하다면, 채널 코드는 대상 정규화와 전송/표시 관련 정보에만 집중시키세요.
openclaw/plugin-sdk/approval-runtime의createChannelExecApprovalProfile,createChannelNativeOriginTargetResolver,createChannelApproverDmTargetResolver,createApproverRestrictedNativeApprovalCapability를 사용하세요. 채널 전용 정보는approvalCapability.nativeRuntime뒤에 두고, 이상적으로는createChannelApprovalNativeRuntimeAdapter(...)또는createLazyChannelApprovalNativeRuntimeAdapter(...)를 통해 두세요. 그러면 코어가 핸들러를 조립하고 요청 필터링, 라우팅, 중복 제거, 만료, gateway 구독, 다른 곳으로 라우팅됨 알림을 담당할 수 있습니다.nativeRuntime은 몇 개의 더 작은 연결 지점으로 나뉩니다: availability— 계정이 설정되었는지, 요청을 처리해야 하는지 여부presentation— 공유 승인 뷰 모델을 보류/해결됨/만료된 네이티브 페이로드 또는 최종 작업으로 매핑transport— 대상을 준비하고 네이티브 승인 메시지를 전송/업데이트/삭제interactions— 네이티브 버튼 또는 반응을 위한 선택적 bind/unbind/clear-action 훅observe— 선택적 전달 진단 훅- 채널에 클라이언트, 토큰, Bolt 앱, 웹훅 리시버 같은 런타임 소유 객체가 필요하다면
openclaw/plugin-sdk/channel-runtime-context를 통해 등록하세요. 일반적인 runtime-context 레지스트리를 사용하면 승인 전용 래퍼 접착 코드를 추가하지 않고도 코어가 채널 시작 상태에서 기능 기반 핸들러를 부트스트랩할 수 있습니다. - 기능 기반 연결 지점으로 아직 충분히 표현할 수 없을 때만 더 낮은 수준의
createChannelApprovalHandler또는createChannelNativeApprovalRuntime을 사용하세요. - 네이티브 승인 채널은
accountId와approvalKind를 모두 해당 헬퍼들을 통해 라우팅해야 합니다.accountId는 다중 계정 승인 정책을 올바른 봇 계정 범위로 유지하고,approvalKind는 코어에 하드코딩된 분기 없이도 채널에서 exec 대 plugin 승인 동작을 사용할 수 있게 합니다. - 이제 코어가 승인 재라우팅 알림도 담당합니다. 채널 plugin은
createChannelNativeApprovalRuntime에서 자체적인 “승인이 DM/다른 채널로 갔음” 후속 메시지를 보내지 말고, 공유 승인 기능 헬퍼를 통해 정확한 origin + approver-DM 라우팅을 노출한 뒤 코어가 시작 채팅에 알림을 게시하기 전에 실제 전달 결과를 집계하게 하세요. - 전달된 승인 id 종류를 처음부터 끝까지 보존하세요. 네이티브 클라이언트는 채널 로컬 상태를 기준으로 exec 대 plugin 승인 라우팅을 추측하거나 다시 쓰면 안 됩니다.
- 서로 다른 승인 종류는 의도적으로 서로 다른 네이티브 표면을 노출할 수 있습니다.
현재 번들 예시는 다음과 같습니다:
- Slack은 exec 및 plugin id 모두에 대해 네이티브 승인 라우팅을 계속 사용할 수 있게 유지합니다.
- Matrix는 exec와 plugin 승인 모두에 대해 동일한 네이티브 DM/채널 라우팅과 반응 UX를 유지하면서도 승인 종류별로 인증이 다를 수 있게 합니다.
createApproverRestrictedNativeApprovalAdapter는 여전히 호환성 래퍼로 존재하지만, 새 코드에서는 기능 빌더를 선호하고 plugin에approvalCapability를 노출해야 합니다.
openclaw/plugin-sdk/approval-auth-runtimeopenclaw/plugin-sdk/approval-client-runtimeopenclaw/plugin-sdk/approval-delivery-runtimeopenclaw/plugin-sdk/approval-gateway-runtimeopenclaw/plugin-sdk/approval-handler-adapter-runtimeopenclaw/plugin-sdk/approval-handler-runtimeopenclaw/plugin-sdk/approval-native-runtimeopenclaw/plugin-sdk/approval-reply-runtimeopenclaw/plugin-sdk/channel-runtime-context
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을 선호하세요.
특히 setup의 경우:
openclaw/plugin-sdk/setup-runtime은 런타임 안전 setup 헬퍼를 다룹니다: import-safe setup 패치 adapter(createPatchedAccountSetupAdapter,createEnvPatchedAccountSetupAdapter,createSetupInputPresenceValidator), lookup-note 출력,promptResolvedAllowFrom,splitSetupEntries, 그리고 위임된 setup-proxy 빌더openclaw/plugin-sdk/setup-adapter-runtime은createEnvPatchedAccountSetupAdapter를 위한 좁은 env 인식 adapter 연결 지점입니다openclaw/plugin-sdk/channel-setup은 선택적 설치 setup 빌더와 몇 가지 setup 안전 기본 요소를 다룹니다:createOptionalChannelSetupSurface,createOptionalChannelSetupAdapter,
channelEnvVars에 이를 선언하세요. 채널 런타임 envVars 또는 로컬 상수는
operator 대상 복사용으로만 유지하세요.
createOptionalChannelSetupWizard, DEFAULT_ACCOUNT_ID,
createTopLevelChannelDmPolicy, setSetupChannelEnabled, 그리고
splitSetupEntries
- 더 무거운 공유 setup/config 헬퍼인
moveSingleAccountChannelSectionToDefaultAccount(...)도 필요할 때만 더 넓은openclaw/plugin-sdk/setup연결 지점을 사용하세요
createOptionalChannelSetupSurface(...)를 선호하세요. 생성된
adapter/wizard는 config 쓰기와 최종화에서 fail closed로 동작하며,
검증, 최종화, 문서 링크 복사 전반에 걸쳐 동일한 설치 필요 메시지를 재사용합니다.
다른 핫 채널 경로에서도 더 넓은 레거시 표면보다 좁은 헬퍼를 선호하세요:
- 다중 계정 config 및
기본 계정 대체를 위한
openclaw/plugin-sdk/account-core,openclaw/plugin-sdk/account-id,openclaw/plugin-sdk/account-resolution, 그리고openclaw/plugin-sdk/account-helpers - 인바운드 경로/envelope 및
record-and-dispatch 연결을 위한
openclaw/plugin-sdk/inbound-envelope와openclaw/plugin-sdk/inbound-reply-dispatch - 대상 파싱/매칭을 위한
openclaw/plugin-sdk/messaging-targets - 미디어 로딩 및 아웃바운드
정체성/send 위임을 위한
openclaw/plugin-sdk/outbound-media와openclaw/plugin-sdk/outbound-runtime - 스레드 바인딩 수명 주기
및 adapter 등록을 위한
openclaw/plugin-sdk/thread-bindings-runtime - 레거시 agent/media
페이로드 필드 레이아웃이 여전히 필요할 때만
openclaw/plugin-sdk/agent-media-payload - Telegram 커스텀 명령 정규화, 중복/충돌 검증,
그리고 대체 안정 명령 config 계약을 위한
openclaw/plugin-sdk/telegram-command-config
인바운드 멘션 정책
인바운드 멘션 처리는 두 계층으로 나누어 유지하세요:- plugin 소유 증거 수집
- 공유 정책 평가
openclaw/plugin-sdk/channel-inbound를 사용하세요.
plugin 로컬 로직에 적합한 항목:
- 봇에 대한 reply 감지
- 봇 인용 감지
- 스레드 참여 확인
- 서비스/시스템 메시지 제외
- 봇 참여를 입증하는 데 필요한 플랫폼 네이티브 캐시
requireMention- 명시적 멘션 결과
- 암시적 멘션 허용 목록
- 명령 우회
- 최종 건너뛰기 결정
- 로컬 멘션 사실을 계산합니다.
- 그 사실을
resolveInboundMentionDecision({ facts, policy })에 전달합니다. - 인바운드 게이트에서
decision.effectiveWasMentioned,decision.shouldBypassMention,decision.shouldSkip를 사용합니다.
api.runtime.channel.mentions는 이미 런타임 주입에 의존하는
번들 채널 plugin을 위해 동일한 공유 멘션 헬퍼를 노출합니다:
buildMentionRegexesmatchesMentionPatternsmatchesMentionWithExplicitimplicitMentionKindWhenresolveInboundMentionDecision
resolveMentionGating* 헬퍼는
openclaw/plugin-sdk/channel-inbound에 호환성 export로만 남아 있습니다. 새 코드는
resolveInboundMentionDecision({ facts, policy })를 사용해야 합니다.
따라 하기
패키지와 manifest
표준 plugin 파일을 만드세요.
package.json의 channel 필드가
이것을 채널 plugin으로 만듭니다. 전체 패키지 메타데이터 표면은
Plugin 설정 및 Config를 참고하세요:채널 plugin 객체 구축
ChannelPlugin 인터페이스에는 선택적인 adapter 표면이 많이 있습니다. 먼저
최소 구성인 id와 setup부터 시작한 뒤, 필요할 때 adapter를 추가하세요.src/channel.ts를 만드세요:src/channel.ts
createChatChannelPlugin이 대신 처리해 주는 일
createChatChannelPlugin이 대신 처리해 주는 일
저수준 adapter 인터페이스를 직접 구현하는 대신 선언적 옵션을 전달하면
빌더가 이를 조합해 줍니다:
완전한 제어가 필요하다면 선언적 옵션 대신 원시 adapter 객체를 전달할 수도 있습니다.
| Option | 연결되는 항목 |
|---|---|
security.dm | config 필드에서 범위가 지정된 DM 보안 resolver |
pairing.text | 코드 교환이 있는 텍스트 기반 DM 페어링 흐름 |
threading | reply-to-mode resolver(고정, 계정 범위, 또는 커스텀) |
outbound.attachedResults | 결과 메타데이터(메시지 ID)를 반환하는 send 함수 |
엔트리포인트 연결
index.ts를 만드세요:index.ts
registerCliMetadata(...)에 두세요. 그러면 OpenClaw가
전체 채널 런타임을 활성화하지 않고도 루트 도움말에 이를 표시할 수 있고,
일반적인 전체 로드도 실제 명령 등록을 위해 동일한 descriptor를 가져오게 됩니다.
registerFull(...)은 런타임 전용 작업에 유지하세요.
registerFull(...)이 gateway RPC 메서드를 등록한다면
plugin 전용 접두사를 사용하세요. 코어 admin 네임스페이스(config.*,
exec.approvals.*, wizard.*, update.*)는 예약되어 있으며 항상
operator.admin으로 해석됩니다.
defineChannelPluginEntry는 등록 모드 분리를 자동으로 처리합니다. 모든
옵션은 엔트리포인트를 참고하세요.setup entry 추가
온보딩 중 경량 로딩을 위해 OpenClaw는 채널이 비활성화되었거나
설정되지 않았을 때 전체 entry 대신 이것을 로드합니다.
이렇게 하면 setup 흐름에서 무거운 런타임 코드를 끌어오지 않게 됩니다.
자세한 내용은 Setup 및 Config를 참고하세요.
setup-entry.ts를 만드세요:setup-entry.ts
인바운드 메시지 처리
plugin은 플랫폼에서 메시지를 받아 OpenClaw로 전달해야 합니다.
일반적인 패턴은 요청을 검증하고
채널의 인바운드 핸들러를 통해 디스패치하는 웹훅입니다:
인바운드 메시지 처리는 채널별입니다. 각 채널 plugin이
자체 인바운드 파이프라인을 담당합니다. 실제 패턴은 번들 채널 plugin
(예: Microsoft Teams 또는 Google Chat plugin 패키지)을 확인하세요.
테스트
파일 구조
고급 주제
스레딩 옵션
고정, 계정 범위, 또는 커스텀 답장 모드
메시지 도구 통합
describeMessageTool 및 작업 검색
대상 해석
inferTargetChatType, looksLikeId, resolveTarget
런타임 헬퍼
api.runtime를 통한 TTS, STT, 미디어, 서브에이전트
일부 번들 헬퍼 연결 지점은 번들 plugin 유지 관리와
호환성을 위해 여전히 존재합니다. 새 채널 plugin에 권장되는 패턴은 아니며,
해당 번들 plugin 계열을 직접 유지 관리하는 경우가 아니라면
일반 SDK 표면의 범용 channel/setup/reply/runtime 하위 경로를 선호하세요.
다음 단계
- Provider Plugin — plugin이 모델도 제공하는 경우
- SDK 개요 — 전체 하위 경로 import 참조
- SDK 테스팅 — 테스트 유틸리티 및 계약 테스트
- Plugin Manifest — 전체 manifest 스키마