Plugins
Kanal Plugin'leri oluşturma
Bu kılavuz, OpenClaw'u bir mesajlaşma platformuna bağlayan bir kanal Plugin'i oluşturmayı adım adım açıklar. Sonunda DM güvenliği, eşleştirme, yanıt iş parçacıkları ve giden mesajlaşma özelliklerine sahip çalışan bir kanalınız olur.
Kanal Plugin'leri nasıl çalışır?
Kanal Plugin'lerinin kendi send/edit/react araçlarına ihtiyacı yoktur. OpenClaw çekirdekte tek bir paylaşılan message aracı tutar. Plugin'iniz şunlardan sorumludur:
- Yapılandırma - hesap çözümleme ve kurulum sihirbazı
- Güvenlik - DM politikası ve izin listeleri
- Eşleştirme - DM onay akışı
- Oturum dil bilgisi - sağlayıcıya özgü konuşma kimliklerinin temel sohbetlere, iş parçacığı kimliklerine ve üst öğe yedeklerine nasıl eşlendiği
- Giden - platforma metin, medya ve anket gönderme
- İş parçacıkları - yanıtların nasıl iş parçacığına alındığı
- Heartbeat yazıyor göstergesi - Heartbeat teslim hedefleri için isteğe bağlı yazıyor/meşgul sinyalleri
Çekirdek; paylaşılan mesaj aracını, istem bağlantılarını, dış oturum anahtarı biçimini, genel :thread: kayıtlarını ve dağıtımı yönetir.
Yeni kanal Plugin'leri ayrıca openclaw/plugin-sdk/channel-message içinden defineChannelMessageAdapter ile bir message bağdaştırıcısı sunmalıdır. Bağdaştırıcı, yerel aktarımın gerçekten desteklediği kalıcı final gönderim yeteneklerini bildirir ve metin/medya gönderimlerini eski outbound bağdaştırıcısıyla aynı aktarım işlevlerine yönlendirir. Bir yeteneği yalnızca bir sözleşme testi yerel yan etkiyi ve dönen alındıyı kanıtladığında bildirin.
Tam API sözleşmesi, örnekler, yetenek matrisi, alındı kuralları, canlı önizleme sonlandırması, alma onayı politikası, testler ve geçiş tablosu için Kanal mesaj API'si bölümüne bakın.
Mevcut outbound bağdaştırıcısı zaten doğru gönderim yöntemlerine ve yetenek meta verilerine sahipse, başka bir köprüyü elle yazmak yerine message bağdaştırıcısını türetmek için createChannelMessageAdapterFromOutbound(...) kullanın.
Bağdaştırıcı gönderimleri MessageReceipt değerleri döndürmelidir. Uyumluluk kodunun hâlâ eski kimliklere ihtiyacı olduğunda, yeni yaşam döngüsü kodunda paralel messageIds alanları tutmak yerine bunları listMessageReceiptPlatformIds(...) veya resolveMessageReceiptPrimaryId(...) ile türetin.
Önizleme destekleyen kanallar ayrıca draftPreview, previewFinalization, progressUpdates, nativeStreaming veya quietFinalization gibi sahip oldukları tam canlı yaşam döngüsüyle message.live.capabilities bildirmelidir. Taslak önizlemeyi yerinde sonlandıran kanallar ayrıca finalEdit, normalFallback, discardPending, previewReceipt ve retainOnAmbiguousFailure gibi message.live.finalizer.capabilities bildirmeli ve çalışma zamanı mantığını defineFinalizableLivePreviewAdapter(...) ile deliverWithFinalizableLivePreviewAdapter(...) üzerinden yönlendirmelidir. Bu yetenekleri verifyChannelMessageLiveCapabilityAdapterProofs(...) ve verifyChannelMessageLiveFinalizerProofs(...) testleriyle destekleyin; böylece yerel önizleme, ilerleme, düzenleme, yedek/tutma, temizleme ve alındı davranışı sessizce sapamaz.
Platform onaylarını erteleyen gelen alıcılar, onay zamanlamasını izleyiciye yerel durumda gizlemek yerine message.receive.defaultAckPolicy ve supportedAckPolicies bildirmelidir. Bildirilen her politikayı verifyChannelMessageReceiveAckPolicyAdapterProofs(...) ile kapsayın.
createChannelTurnReplyPipeline, dispatchInboundReplyWithBase ve recordInboundSessionAndDispatchReply gibi eski yanıt/tur yardımcıları uyumluluk dağıtıcıları için kullanılabilir durumda kalır. Yeni kanal kodu için bu adları kullanmayın; yeni Plugin'ler openclaw/plugin-sdk/channel-message üzerindeki message bağdaştırıcısı, alındılar ve alma/gönderme yaşam döngüsü yardımcılarıyla başlamalıdır.
Kanalınız gelen yanıtların dışında yazıyor göstergelerini destekliyorsa, kanal Plugin'inde heartbeat.sendTyping(...) sunun. Çekirdek bunu Heartbeat model çalışması başlamadan önce çözümlenen Heartbeat teslim hedefiyle çağırır ve paylaşılan yazıyor göstergesi keepalive/temizleme yaşam döngüsünü kullanır. Platform açık bir durdurma sinyaline ihtiyaç duyuyorsa heartbeat.clearTyping(...) ekleyin.
Kanalınız medya kaynakları taşıyan mesaj aracı parametreleri ekliyorsa, bu parametre adlarını describeMessageTool(...).mediaSourceParams üzerinden sunun. Çekirdek bu açık listeyi sandbox yol normalleştirmesi ve giden medya erişim politikası için kullanır; böylece Plugin'ler sağlayıcıya özgü avatar, ek veya kapak görseli parametreleri için paylaşılan çekirdekte özel durumlara ihtiyaç duymaz.
İlgisiz eylemlerin başka bir eylemin medya argümanlarını devralmaması için { "set-profile": ["avatarUrl", "avatarPath"] } gibi eylem anahtarlı bir harita döndürmeyi tercih edin. Düz dizi, kasıtlı olarak açığa çıkarılan her eylemde paylaşılan parametreler için hâlâ çalışır.
Kanalınız message(action="send") için sağlayıcıya özgü biçimlendirme gerektiriyorsa, actions.prepareSendPayload(...) kullanmayı tercih edin. Yerel kartları, blokları, embed'leri veya diğer kalıcı verileri payload.channelData.<channel> altına koyun ve gerçek gönderimi çekirdeğin outbound/message bağdaştırıcısı üzerinden yapmasına izin verin. actions.handleAction(...) işlevini gönderim için yalnızca serileştirilemeyen ve yeniden denenemeyen yüklerde uyumluluk yedeği olarak kullanın.
Platformunuz konuşma kimlikleri içinde ek kapsam depoluyorsa, bu ayrıştırmayı Plugin içinde messaging.resolveSessionConversation(...) ile tutun. Bu, rawId değerini temel konuşma kimliğine, isteğe bağlı iş parçacığı kimliğine, açık baseConversationId değerine ve tüm parentConversationCandidates değerlerine eşlemek için kanonik kancadır.
parentConversationCandidates döndürdüğünüzde, bunları en dar üst öğeden en geniş/temel konuşmaya doğru sıralı tutun.
Plugin kodunun rota benzeri alanları normalleştirmesi, alt iş parçacığını üst rotasıyla karşılaştırması veya { channel, to, accountId, threadId } değerinden kararlı bir tekilleştirme anahtarı oluşturması gerektiğinde openclaw/plugin-sdk/channel-route kullanın. Yardımcı, sayısal iş parçacığı kimliklerini çekirdekle aynı şekilde normalleştirir; bu nedenle Plugin'ler geçici String(threadId) karşılaştırmaları yerine bunu tercih etmelidir.
Sağlayıcıya özgü hedef dil bilgisine sahip Plugin'ler ayrıştırıcılarını resolveChannelRouteTargetWithParser(...) içine enjekte edebilir ve yine çekirdeğin kullandığı aynı rota hedef biçimini ve iş parçacığı yedek semantiklerini elde edebilir.
Kanal kayıt defteri başlamadan önce aynı ayrıştırmaya ihtiyaç duyan birlikte gelen Plugin'ler, eşleşen bir resolveSessionConversation(...) dışa aktarımıyla üst düzey bir session-key-api.ts dosyası da sunabilir. Çekirdek bu önyükleme açısından güvenli yüzeyi yalnızca çalışma zamanı Plugin kayıt defteri henüz kullanılabilir olmadığında kullanır.
messaging.resolveParentConversationCandidates(...), bir Plugin'in genel/ham kimliğin üstünde yalnızca üst öğe yedeklerine ihtiyaç duyduğu durumlarda eski uyumluluk yedeği olarak kullanılabilir durumda kalır. Her iki kanca da varsa çekirdek önce resolveSessionConversation(...).parentConversationCandidates değerini kullanır ve yalnızca kanonik kanca bunları atladığında resolveParentConversationCandidates(...) yedeğine döner.
Onaylar ve kanal yetenekleri
Çoğu kanal Plugin'i onaya özgü koda ihtiyaç duymaz.
- Çekirdek, aynı sohbet
/approvekomutuna, paylaşılan onay düğmesi yüklerine ve genel yedek teslimata sahip olur. - Kanal onaya özgü davranış gerektirdiğinde kanal Plugin'inde tek bir
approvalCapabilitynesnesini tercih edin. ChannelPlugin.approvalskaldırıldı. Onay teslimatı/native/render/auth bilgileriniapprovalCapabilityüzerine koyun.plugin.authyalnızca oturum açma/oturumu kapatmadır; çekirdek artık onay auth kancalarını bu nesneden okumaz.approvalCapability.authorizeActorActionveapprovalCapability.getActionAvailabilityState, standart onay-auth sınırıdır.- Aynı sohbet onay auth kullanılabilirliği için
approvalCapability.getActionAvailabilityStatekullanın. - Kanalınız native exec onayları sunuyorsa, başlatan yüzey/native-client durumu aynı sohbet onay auth durumundan farklı olduğunda bunun için
approvalCapability.getExecInitiatingSurfaceStatekullanın. Çekirdek,enablediledisabledarasında ayrım yapmak, başlatan kanalın native exec onaylarını destekleyip desteklemediğine karar vermek ve kanalı native-client yedek rehberliğine dahil etmek için exec'e özgü bu kancayı kullanır.createApproverRestrictedNativeApprovalCapability(...)yaygın durum için bunu doldurur. - Yinelenen yerel onay istemlerini gizleme veya teslimattan önce yazıyor göstergeleri gönderme gibi kanala özgü yük yaşam döngüsü davranışları için
outbound.shouldSuppressLocalPayloadPromptveyaoutbound.beforeDeliverPayloadkullanın. approvalCapability.deliveryöğesini yalnızca native onay yönlendirmesi veya yedek bastırma için kullanın.- Kanalın sahip olduğu native onay bilgileri için
approvalCapability.nativeRuntimekullanın. Bunu, çekirdeğin onay yaşam döngüsünü birleştirmesine yine de izin verirken runtime modülünüzü gerektiğinde içe aktarabilencreateLazyChannelApprovalNativeRuntimeAdapter(...)ile sıcak kanal giriş noktalarında lazy tutun. approvalCapability.renderöğesini yalnızca bir kanal paylaşılan renderer yerine gerçekten özel onay yüklerine ihtiyaç duyduğunda kullanın.- Kanal, devre dışı yol yanıtının native exec onaylarını etkinleştirmek için gereken tam yapılandırma düğmelerini açıklamasını istediğinde
approvalCapability.describeExecApprovalSetupkullanın. Kanca{ channel, channelLabel, accountId }alır; adlandırılmış hesap kanalları, üst düzey varsayılanlar yerinechannels.<channel>.accounts.<id>.execApprovals.*gibi hesap kapsamlı yollar render etmelidir. - Bir kanal mevcut yapılandırmadan kararlı owner benzeri DM kimlikleri çıkarabiliyorsa, onaya özgü çekirdek mantığı eklemeden aynı sohbet
/approvekomutunu kısıtlamak içinopenclaw/plugin-sdk/approval-runtimeiçindekicreateResolvedApproverActionAuthAdapteröğesini kullanın. - Bir kanal native onay teslimatına ihtiyaç duyuyorsa, kanal kodunu hedef normalleştirme ve taşıma/sunum bilgilerine odaklı tutun.
openclaw/plugin-sdk/approval-runtimeiçindencreateChannelExecApprovalProfile,createChannelNativeOriginTargetResolver,createChannelApproverDmTargetResolvervecreateApproverRestrictedNativeApprovalCapabilitykullanın. Kanala özgü bilgileri, ideal olarakcreateChannelApprovalNativeRuntimeAdapter(...)veyacreateLazyChannelApprovalNativeRuntimeAdapter(...)aracılığıylaapprovalCapability.nativeRuntimearkasına koyun; böylece çekirdek handler'ı birleştirip istek filtrelemeye, yönlendirmeye, tekilleştirmeye, süre dolumuna, gateway aboneliğine ve başka yere yönlendirildi bildirimlerine sahip olabilir.nativeRuntimebirkaç daha küçük sınıra ayrılır: createChannelNativeOriginTargetResolver,{ to, accountId, threadId }hedefleri için varsayılan olarak paylaşılan kanal-route eşleştiricisini kullanır. Yalnızca bir kanalın Slack zaman damgası öneki eşleştirme gibi sağlayıcıya özgü eşdeğerlik kuralları olduğundatargetsMatchgeçirin.- Kanalın, varsayılan route eşleştiricisi veya özel bir
targetsMatchcallback'i çalışmadan önce sağlayıcı id'lerini standartlaştırması, ancak teslimat için özgün hedefi koruması gerektiğindecreateChannelNativeOriginTargetResolveröğesinenormalizeTargetForMatchgeçirin.normalizeTargetöğesini yalnızca çözümlenmiş teslimat hedefinin kendisi standartlaştırılmalıysa kullanın. availability- hesabın yapılandırılıp yapılandırılmadığı ve bir isteğin işlenip işlenmeyeceğipresentation- paylaşılan onay görünüm modelini bekleyen/çözümlenmiş/süresi dolmuş native yüklere veya son eylemlere eşleyintransport- hedefleri hazırlayın ve native onay mesajlarını gönderin/güncelleyin/silininteractions- native düğmeler veya tepkiler için isteğe bağlı bind/unbind/clear-action kancalarıobserve- isteğe bağlı teslimat tanılama kancaları- Kanal, client, token, Bolt app veya webhook receiver gibi runtime'a ait nesnelere ihtiyaç duyuyorsa bunları
openclaw/plugin-sdk/channel-runtime-contextüzerinden kaydedin. Genel runtime-context registry, çekirdeğin onaya özgü wrapper glue eklemeden kanal başlangıç durumundan capability odaklı handler'ları başlatmasına izin verir. - Daha düşük seviyeli
createChannelApprovalHandlerveyacreateChannelNativeApprovalRuntimeöğelerine yalnızca capability odaklı sınır henüz yeterince ifade gücüne sahip olmadığında başvurun. - Native onay kanalları hem
accountIdhem deapprovalKinddeğerlerini bu yardımcılar üzerinden yönlendirmelidir.accountId, çok hesaplı onay ilkesini doğru bot hesabı kapsamında tutar veapprovalKind, çekirdekte sabit kodlanmış dallar olmadan exec ile Plugin onay davranışını kanal için kullanılabilir tutar. - Çekirdek artık onay yeniden yönlendirme bildirimlerine de sahip olur. Kanal Plugin'leri
createChannelNativeApprovalRuntimeiçinden kendi "onay DM'lere / başka bir kanala gitti" takip mesajlarını göndermemelidir; bunun yerine paylaşılan onay capability yardımcıları üzerinden doğru origin + approver-DM yönlendirmesini sunmalı ve başlatan sohbete herhangi bir bildirim göndermeden önce çekirdeğin gerçek teslimatları toplamasına izin vermelidir. - Teslim edilen onay id türünü uçtan uca koruyun. Native client'lar, exec ile Plugin onay yönlendirmesini kanal yerel durumundan tahmin etmemeli veya yeniden yazmamalıdır.
- Farklı onay türleri bilinçli olarak farklı native yüzeyler sunabilir. Mevcut paketli örnekler:
- Slack, native onay yönlendirmesini hem exec hem de Plugin id'leri için kullanılabilir tutar.
- Matrix, auth'un onay türüne göre farklılaşmasına yine de izin verirken exec ve Plugin onayları için aynı native DM/kanal yönlendirmesini ve tepki UX'ini korur.
createApproverRestrictedNativeApprovalAdapterhâlâ bir uyumluluk wrapper'ı olarak vardır, ancak yeni kod capability builder'ı tercih etmeli ve Plugin üzerindeapprovalCapabilitysunmalıdır.
Sıcak kanal giriş noktaları için, o ailenin yalnızca bir parçasına ihtiyaç duyduğunuzda daha dar runtime alt yollarını tercih edin:
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
Benzer şekilde, daha geniş şemsiye yüzeye ihtiyaç duymadığınızda 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 ve
openclaw/plugin-sdk/reply-chunking tercih edin.
Özellikle setup için:
openclaw/plugin-sdk/setup-runtime, runtime açısından güvenli setup yardımcılarını kapsar: içe aktarma açısından güvenli setup patch adapter'ları (createPatchedAccountSetupAdapter,createEnvPatchedAccountSetupAdapter,createSetupInputPresenceValidator), lookup-note çıktısı,promptResolvedAllowFrom,splitSetupEntriesve devredilmiş setup-proxy builder'larıopenclaw/plugin-sdk/setup-adapter-runtime,createEnvPatchedAccountSetupAdapteriçin dar env-aware adapter sınırıdıropenclaw/plugin-sdk/channel-setup, optional-install setup builder'larını ve birkaç setup açısından güvenli primitive'i kapsar:createOptionalChannelSetupSurface,createOptionalChannelSetupAdapter,
Kanalınız env odaklı setup veya auth destekliyorsa ve genel başlangıç/yapılandırma akışlarının runtime yüklenmeden önce bu env adlarını bilmesi gerekiyorsa, bunları Plugin manifest'inde channelEnvVars ile bildirin. Kanal runtime envVars veya yerel sabitleri yalnızca operatöre yönelik metinler için tutun.
Kanalınız Plugin runtime başlamadan önce status, channels list, channels status veya SecretRef taramalarında görünebiliyorsa, package.json içine openclaw.setupEntry ekleyin. Bu giriş noktası salt okunur komut yollarında içe aktarılması güvenli olmalı ve bu özetler için gereken kanal metadata'sını, setup açısından güvenli config adapter'ını, status adapter'ını ve kanal secret hedef metadata'sını döndürmelidir. Setup entry'den client, listener veya transport runtime başlatmayın.
Ana kanal entry import yolunu da dar tutun. Discovery, kanalı etkinleştirmeden capability'leri kaydetmek için entry'yi ve kanal Plugin modülünü değerlendirebilir. channel-plugin-api.ts gibi dosyalar, setup wizard'larını, transport client'larını, socket listener'larını, subprocess launcher'larını veya service startup modüllerini içe aktarmadan kanal Plugin nesnesini dışa aktarmalıdır. Bu runtime parçalarını registerFull(...), runtime setter'ları veya lazy capability adapter'larından yüklenen modüllere koyun.
createOptionalChannelSetupWizard, DEFAULT_ACCOUNT_ID,
createTopLevelChannelDmPolicy, setSetupChannelEnabled ve
splitSetupEntries
- daha geniş
openclaw/plugin-sdk/setupsınırını yalnızcamoveSingleAccountChannelSectionToDefaultAccount(...)gibi daha ağır paylaşılan setup/config yardımcılarına da ihtiyaç duyduğunuzda kullanın
Kanalınız setup yüzeylerinde yalnızca "önce bu Plugin'i yükleyin" mesajını duyurmak istiyorsa, createOptionalChannelSetupSurface(...) tercih edin. Üretilen adapter/wizard, config yazma ve finalization aşamalarında güvenli şekilde kapalı kalır ve validation, finalize ve docs-link metninde aynı kurulum gerekli mesajını yeniden kullanır.
Diğer sıcak kanal yolları için, daha geniş eski yüzeyler yerine dar yardımcıları tercih edin:
- Çok hesaplı config ve varsayılan hesap fallback'i için
openclaw/plugin-sdk/account-core,openclaw/plugin-sdk/account-id,openclaw/plugin-sdk/account-resolutionveopenclaw/plugin-sdk/account-helpers - inbound route/envelope ve record-and-dispatch bağlantıları için
openclaw/plugin-sdk/inbound-envelopeveopenclaw/plugin-sdk/inbound-reply-dispatch - hedef ayrıştırma/eşleştirme için
openclaw/plugin-sdk/messaging-targets - medya yükleme ile outbound identity/send delegate'leri ve yük planlama için
openclaw/plugin-sdk/outbound-mediaveopenclaw/plugin-sdk/outbound-runtime - Bir outbound route, açık bir
replyToId/threadIddeğerini korumalı veya temel session key hâlâ eşleştiğinde geçerli:thread:session'ını kurtarmalıysaopenclaw/plugin-sdk/channel-coreiçindekibuildThreadAwareOutboundSessionRoute(...). Provider Plugin'leri, platformlarının native thread teslimat semantiği olduğunda önceliği, suffix davranışını ve thread id normalleştirmesini geçersiz kılabilir. - thread-binding yaşam döngüsü ve adapter kaydı için
openclaw/plugin-sdk/thread-bindings-runtime - yalnızca legacy agent/media yük alanı düzeni hâlâ gerekli olduğunda
openclaw/plugin-sdk/agent-media-payload - Telegram özel komut normalleştirme, yinelenen/çakışan doğrulama ve fallback açısından kararlı komut config sözleşmesi için
openclaw/plugin-sdk/telegram-command-config
Yalnızca auth kullanan kanallar genellikle varsayılan yolda durabilir: çekirdek onayları işler ve Plugin yalnızca outbound/auth capability'leri sunar. Matrix, Slack, Telegram ve özel chat transport'ları gibi native onay kanalları, kendi onay yaşam döngülerini yazmak yerine paylaşılan native yardımcıları kullanmalıdır.
Inbound mention ilkesi
Inbound mention işlemeyi iki katmana ayrılmış tutun:
- Plugin'e ait kanıt toplama
- paylaşılan ilke değerlendirmesi
Mention-policy kararları için openclaw/plugin-sdk/channel-mention-gating kullanın.
Daha geniş inbound helper barrel'a ihtiyaç duyduğunuzda yalnızca openclaw/plugin-sdk/channel-inbound kullanın.
Plugin yerel mantığı için iyi uyum:
- reply-to-bot algılama
- quoted-bot algılama
- thread katılımı kontrolleri
- service/system-message hariç tutmaları
- bot katılımını kanıtlamak için gereken platform-native cache'ler
Paylaşılan yardımcı için iyi uyum:
requireMention- açık bahsetme sonucu
- örtük bahsetme izin listesi
- komut baypası
- son atlama kararı
Tercih edilen akış:
- Yerel bahsetme olgularını hesaplayın.
- Bu olguları
resolveInboundMentionDecision({ facts, policy })içine iletin. - Gelen kapınızda
decision.effectiveWasMentioned,decision.shouldBypassMentionvedecision.shouldSkipkullanın.
implicitMentionKindWhen,
matchesMentionWithExplicit,
resolveInboundMentionDecision,
} from "openclaw/plugin-sdk/channel-inbound";
const mentionMatch = matchesMentionWithExplicit(text, {
mentionRegexes,
mentionPatterns,
});
const facts = {
canDetectMention: true,
wasMentioned: mentionMatch.matched,
hasAnyMention: mentionMatch.hasExplicitMention,
implicitMentionKinds: [
...implicitMentionKindWhen("reply_to_bot", isReplyToBot),
...implicitMentionKindWhen("quoted_bot", isQuoteOfBot),
],
};
const decision = resolveInboundMentionDecision({
facts,
policy: {
isGroup,
requireMention,
allowedImplicitMentionKinds: requireExplicitMention ? [] : ["reply_to_bot", "quoted_bot"],
allowTextCommands,
hasControlCommand,
commandAuthorized,
},
});
if (decision.shouldSkip) return;
api.runtime.channel.mentions, zaten çalışma zamanı enjeksiyonuna bağlı olan
paketli kanal Plugin’leri için aynı paylaşılan bahsetme yardımcılarını sunar:
buildMentionRegexesmatchesMentionPatternsmatchesMentionWithExplicitimplicitMentionKindWhenresolveInboundMentionDecision
Yalnızca implicitMentionKindWhen ve
resolveInboundMentionDecision gerekiyorsa, ilgisiz gelen çalışma zamanı
yardımcılarını yüklememek için
openclaw/plugin-sdk/channel-mention-gating içinden içe aktarın.
Eski resolveMentionGating* yardımcıları,
yalnızca uyumluluk dışa aktarımları olarak
openclaw/plugin-sdk/channel-inbound üzerinde kalır. Yeni kod
resolveInboundMentionDecision({ facts, policy }) kullanmalıdır.
İzlenecek Yol
Paket ve manifest
Standart Plugin dosyalarını oluşturun. package.json içindeki channel alanı,
bunu bir kanal Plugin’i yapan şeydir. Tam paket meta verisi yüzeyi için
Plugin Kurulumu ve Yapılandırması bölümüne bakın:
{
"name": "@myorg/openclaw-acme-chat",
"version": "1.0.0",
"type": "module",
"openclaw": {
"extensions": ["./index.ts"],
"setupEntry": "./setup-entry.ts",
"channel": {
"id": "acme-chat",
"label": "Acme Chat",
"blurb": "Connect OpenClaw to Acme Chat."
}
}
}
{
"id": "acme-chat",
"kind": "channel",
"channels": ["acme-chat"],
"name": "Acme Chat",
"description": "Acme Chat channel plugin",
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {}
},
"channelConfigs": {
"acme-chat": {
"schema": {
"type": "object",
"additionalProperties": false,
"properties": {
"token": { "type": "string" },
"allowFrom": {
"type": "array",
"items": { "type": "string" }
}
}
},
"uiHints": {
"token": {
"label": "Bot token",
"sensitive": true
}
}
}
}
}
configSchema, plugins.entries.acme-chat.config değerini doğrular. Bunu,
kanal hesap yapılandırması olmayan Plugin’e ait ayarlar için kullanın. channelConfigs,
channels.acme-chat değerini doğrular ve Plugin çalışma zamanı yüklenmeden önce
yapılandırma şeması, kurulum ve UI yüzeyleri tarafından kullanılan soğuk yol kaynağıdır.
Kanal Plugin nesnesini oluşturun
ChannelPlugin arayüzünde birçok isteğe bağlı adaptör yüzeyi vardır. En düşük
gereksinimle, yani id ve setup ile başlayın ve gerektikçe adaptörler ekleyin.
src/channel.ts oluşturun:
import {
createChatChannelPlugin,
createChannelPluginBase,
} from "openclaw/plugin-sdk/channel-core";
import type { OpenClawConfig } from "openclaw/plugin-sdk/channel-core";
import { acmeChatApi } from "./client.js"; // your platform API client
type ResolvedAccount = {
accountId: string | null;
token: string;
allowFrom: string[];
dmPolicy: string | undefined;
};
function resolveAccount(
cfg: OpenClawConfig,
accountId?: string | null,
): ResolvedAccount {
const section = (cfg.channels as Record<string, any>)?.["acme-chat"];
const token = section?.token;
if (!token) throw new Error("acme-chat: token is required");
return {
accountId: accountId ?? null,
token,
allowFrom: section?.allowFrom ?? [],
dmPolicy: section?.dmSecurity,
};
}
export const acmeChatPlugin = createChatChannelPlugin<ResolvedAccount>({
base: createChannelPluginBase({
id: "acme-chat",
setup: {
resolveAccount,
inspectAccount(cfg, accountId) {
const section =
(cfg.channels as Record<string, any>)?.["acme-chat"];
return {
enabled: Boolean(section?.token),
configured: Boolean(section?.token),
tokenStatus: section?.token ? "available" : "missing",
};
},
},
}),
// DM security: who can message the bot
security: {
dm: {
channelKey: "acme-chat",
resolvePolicy: (account) => account.dmPolicy,
resolveAllowFrom: (account) => account.allowFrom,
defaultPolicy: "allowlist",
},
},
// Pairing: approval flow for new DM contacts
pairing: {
text: {
idLabel: "Acme Chat username",
message: "Send this code to verify your identity:",
notify: async ({ target, code }) => {
await acmeChatApi.sendDm(target, `Pairing code: ${code}`);
},
},
},
// Threading: how replies are delivered
threading: { topLevelReplyToMode: "reply" },
// Outbound: send messages to the platform
outbound: {
attachedResults: {
sendText: async (params) => {
const result = await acmeChatApi.sendMessage(
params.to,
params.text,
);
return { messageId: result.id };
},
},
base: {
sendMedia: async (params) => {
await acmeChatApi.sendFile(params.to, params.filePath);
},
},
},
});
Hem kurallı üst düzey DM anahtarlarını hem de eski iç içe anahtarları kabul eden kanallar için plugin-sdk/channel-config-helpers içindeki yardımcıları kullanın: resolveChannelDmAccess, resolveChannelDmPolicy, resolveChannelDmAllowFrom ve normalizeChannelDmPolicy, hesaba yerel değerleri devralınan kök değerlerin önünde tutar. Çalışma zamanı ve geçiş aynı sözleşmeyi okusun diye aynı çözümleyiciyi normalizeLegacyDmAliases üzerinden doctor onarımıyla eşleştirin.
createChatChannelPlugin sizin için ne yapar
Düşük düzeyli adaptör arayüzlerini elle uygulamak yerine, bildirime dayalı seçenekler iletirsiniz ve oluşturucu bunları birleştirir:
| Seçenek | Ne bağlar |
|---|---|
security.dm |
Yapılandırma alanlarından kapsamlı DM güvenlik çözümleyicisi |
pairing.text |
Kod değişimiyle metin tabanlı DM eşleştirme akışı |
threading |
Yanıtlama modu çözümleyicisi (sabit, hesap kapsamlı veya özel) |
outbound.attachedResults |
Sonuç meta verisi (ileti kimlikleri) döndüren gönderme işlevleri |
Tam denetim gerekiyorsa bildirime dayalı seçenekler yerine ham adaptör nesneleri de iletebilirsiniz.
Ham giden adaptörler bir chunker(text, limit, ctx) işlevi tanımlayabilir.
İsteğe bağlı ctx.formatting, maxLinesPerMessage gibi teslim zamanlı
biçimlendirme kararlarını taşır; bunu göndermeden önce uygulayın, böylece
yanıt iş parçacığı ve parça sınırları paylaşılan giden teslim tarafından
bir kez çözümlenir. Gönderme bağlamları, yerel bir yanıt hedefi çözümlendiğinde
replyToIdSource (implicit veya explicit) bilgisini de içerir; böylece
yük yardımcıları, örtük tek kullanımlık yanıt yuvasını tüketmeden açık yanıt
etiketlerini koruyabilir.
Giriş noktasını bağlayın
index.ts oluşturun:
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
import { acmeChatPlugin } from "./src/channel.js";
export default defineChannelPluginEntry({
id: "acme-chat",
name: "Acme Chat",
description: "Acme Chat channel plugin",
plugin: acmeChatPlugin,
registerCliMetadata(api) {
api.registerCli(
({ program }) => {
program
.command("acme-chat")
.description("Acme Chat management");
},
{
descriptors: [
{
name: "acme-chat",
description: "Acme Chat management",
hasSubcommands: false,
},
],
},
);
},
registerFull(api) {
api.registerGatewayMethod(/* ... */);
},
});
Kanalın sahip olduğu CLI tanımlayıcılarını registerCliMetadata(...) içine koyun;
böylece OpenClaw, tam kanal çalışma zamanını etkinleştirmeden bunları kök yardımda
gösterebilir, normal tam yüklemeler ise gerçek komut kaydı için aynı
tanımlayıcıları almaya devam eder. registerFull(...) öğesini yalnızca çalışma
zamanı işleri için tutun.
registerFull(...) Gateway RPC yöntemleri kaydediyorsa, Plugin’e özgü bir
önek kullanın. Çekirdek yönetici ad alanları (config.*,
exec.approvals.*, wizard.*, update.*) ayrılmış kalır ve her zaman
operator.admin olarak çözümlenir.
defineChannelPluginEntry, kayıt modu ayrımını otomatik olarak işler. Tüm
seçenekler için Giriş Noktaları bölümüne bakın.
Kurulum girişi ekleyin
Onboarding sırasında hafif yükleme için setup-entry.ts oluşturun:
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";
import { acmeChatPlugin } from "./src/channel.js";
export default defineSetupPluginEntry(acmeChatPlugin);
Kanal devre dışı veya yapılandırılmamış olduğunda OpenClaw, tam giriş yerine bunu yükler. Kurulum akışları sırasında ağır çalışma zamanı kodunu içeri çekmekten kaçınır. Ayrıntılar için Kurulum ve Yapılandırma bölümüne bakın.
Kurulum açısından güvenli dışa aktarımları yan modüllere ayıran paketli çalışma alanı
kanalları, açık bir kurulum zamanı çalışma zamanı ayarlayıcısına da ihtiyaç duyduklarında
openclaw/plugin-sdk/channel-entry-contract içinden
defineBundledChannelSetupEntry(...) kullanabilir.
Gelen iletileri işleyin
Plugin’inizin platformdan iletiler alıp bunları OpenClaw’a iletmesi gerekir. Tipik kalıp, isteği doğrulayan ve kanalınızın gelen işleyicisi üzerinden dağıtan bir Webhook’tur:
registerFull(api) {
api.registerHttpRoute({
path: "/acme-chat/webhook",
auth: "plugin", // plugin-managed auth (verify signatures yourself)
handler: async (req, res) => {
const event = parseWebhookPayload(req);
// Your inbound handler dispatches the message to OpenClaw.
// The exact wiring depends on your platform SDK -
// see a real example in the bundled Microsoft Teams or Google Chat plugin package.
await handleAcmeChatInbound(api, event);
res.statusCode = 200;
res.end("ok");
return true;
},
});
}
Test
src/channel.test.ts içinde aynı konumda testler yazın:
import { describe, it, expect } from "vitest";
import { acmeChatPlugin } from "./channel.js";
describe("acme-chat plugin", () => {
it("resolves account from config", () => {
const cfg = {
channels: {
"acme-chat": { token: "test-token", allowFrom: ["user1"] },
},
} as any;
const account = acmeChatPlugin.setup!.resolveAccount(cfg, undefined);
expect(account.token).toBe("test-token");
});
it("inspects account without materializing secrets", () => {
const cfg = {
channels: { "acme-chat": { token: "test-token" } },
} as any;
const result = acmeChatPlugin.setup!.inspectAccount!(cfg, undefined);
expect(result.configured).toBe(true);
expect(result.tokenStatus).toBe("available");
});
it("reports missing config", () => {
const cfg = { channels: {} } as any;
const result = acmeChatPlugin.setup!.inspectAccount!(cfg, undefined);
expect(result.configured).toBe(false);
});
});
pnpm test -- <bundled-plugin-root>/acme-chat/
Paylaşılan test yardımcıları için bkz. Test Etme.
Dosya yapısı
<bundled-plugin-root>/acme-chat/
├── package.json # openclaw.channel metadata
├── openclaw.plugin.json # Manifest with config schema
├── index.ts # defineChannelPluginEntry
├── setup-entry.ts # defineSetupPluginEntry
├── api.ts # Public exports (optional)
├── runtime-api.ts # Internal runtime exports (optional)
└── src/
├── channel.ts # ChannelPlugin via createChatChannelPlugin
├── channel.test.ts # Tests
├── client.ts # Platform API client
└── runtime.ts # Runtime store (if needed)
Gelişmiş konular
Sabit, hesap kapsamlı veya özel yanıt modları
describeMessageTool ve eylem keşfi
inferTargetChatType, looksLikeId, resolveTarget
TTS, STT, medya, api.runtime üzerinden alt aracı
Paylaşılan gelen tur yaşam döngüsü: alma, çözümleme, kaydetme, gönderme, sonlandırma
Sonraki adımlar
- Sağlayıcı Plugin'leri - Plugin'iniz modeller de sağlıyorsa
- SDK Genel Bakışı - tam alt yol içe aktarma başvurusu
- SDK Test Etme - test yardımcı programları ve sözleşme testleri
- Plugin Manifest - tam manifest şeması