Deze handleiding beschrijft hoe je een kanaalplugin bouwt die OpenClaw met een berichtenplatform verbindt. Aan het einde heb je een werkend kanaal met DM-beveiliging, koppeling, antwoord-threading en uitgaande berichten.Documentation Index
Fetch the complete documentation index at: https://docs.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
Als je nog niet eerder een OpenClaw-plugin hebt gebouwd, lees dan eerst
Aan de slag voor de basale pakketstructuur
en manifestconfiguratie.
Hoe kanaalplugins werken
Kanaalplugins hebben geen eigen tools voor verzenden/bewerken/reageren nodig. OpenClaw behoudt één gedeeldemessage-tool in de core. Je plugin is eigenaar van:
- Configuratie — accountresolutie en installatiewizard
- Beveiliging — DM-beleid en allowlists
- Koppeling — DM-goedkeuringsflow
- Sessiesyntaxis — hoe providerspecifieke gespreks-id’s worden gekoppeld aan basischats, thread-id’s en bovenliggende fallbacks
- Uitgaand — tekst, media en polls naar het platform verzenden
- Threading — hoe antwoorden in threads worden geplaatst
- Heartbeat-typen — optionele type-/bezet-signalen voor Heartbeat-bezorgdoelen
:thread:-boekhouding en dispatch.
Als je kanaal type-indicatoren buiten inkomende antwoorden ondersteunt, expose dan
heartbeat.sendTyping(...) op de kanaalplugin. Core roept dit aan met het
opgeloste Heartbeat-bezorgdoel voordat de Heartbeat-modelrun start en
gebruikt de gedeelde lifecycle voor type-keepalive en opschoning. Voeg heartbeat.clearTyping(...)
toe wanneer het platform een expliciet stopsignaal nodig heeft.
Als je kanaal berichtentoolparameters toevoegt die mediabronnen bevatten, expose dan die
parameternamen via describeMessageTool(...).mediaSourceParams. Core gebruikt
die expliciete lijst voor sandbox-padnormalisatie en uitgaand mediatoegangsbeleid,
zodat plugins geen gedeelde-core-special cases nodig hebben voor providerspecifieke
avatar-, bijlage- of omslagafbeeldingsparameters.
Geef bij voorkeur een op actie gebaseerde map terug, zoals
{ "set-profile": ["avatarUrl", "avatarPath"] }, zodat niet-gerelateerde acties
niet de media-argumenten van een andere actie erven. Een platte array werkt nog steeds voor parameters die
bewust door elke geëxposede actie worden gedeeld.
Als je platform extra scope in gespreks-id’s opslaat, houd die parsing
in de plugin met messaging.resolveSessionConversation(...). Dat is de
canonieke hook voor het koppelen van rawId aan het basisgespreks-id, optioneel thread-id,
expliciet baseConversationId en eventuele parentConversationCandidates.
Wanneer je parentConversationCandidates teruggeeft, houd ze dan geordend van de
smalste parent naar het breedste/basisgesprek.
Gebruik openclaw/plugin-sdk/channel-route wanneer plugincode route-achtige velden moet normaliseren,
een child-thread met de parent-route moet vergelijken, of een
stabiele dedupe-sleutel moet bouwen uit { channel, to, accountId, threadId }. De helper
normaliseert numerieke thread-id’s op dezelfde manier als core, dus plugins moeten deze verkiezen
boven ad-hocvergelijkingen met String(threadId).
Plugins met providerspecifieke doelsyntaxis kunnen hun parser injecteren in
resolveChannelRouteTargetWithParser(...) en nog steeds dezelfde routedoelvorm
en thread-fallbacksemantiek krijgen die core gebruikt.
Gebundelde plugins die dezelfde parsing nodig hebben voordat het kanaalregister opstart,
kunnen ook een top-level session-key-api.ts-bestand exposen met een overeenkomende
resolveSessionConversation(...)-export. Core gebruikt dat bootstrap-veilige oppervlak
alleen wanneer het runtime-pluginregister nog niet beschikbaar is.
messaging.resolveParentConversationCandidates(...) blijft beschikbaar als een
legacy compatibiliteitsfallback wanneer een plugin alleen parent-fallbacks bovenop
het generieke/raw-id nodig heeft. Als beide hooks bestaan, gebruikt core eerst
resolveSessionConversation(...).parentConversationCandidates en valt alleen
terug op resolveParentConversationCandidates(...) wanneer de canonieke hook
ze weglaat.
Goedkeuringen en kanaalmogelijkheden
De meeste kanaalplugins hebben geen goedkeuringsspecifieke code nodig.- Core is eigenaar van same-chat
/approve, gedeelde payloads voor goedkeuringsknoppen en generieke fallbackbezorging. - Geef de voorkeur aan één
approvalCapability-object op de kanaalplugin wanneer het kanaal goedkeuringsspecifiek gedrag nodig heeft. ChannelPlugin.approvalsis verwijderd. Zet feiten over goedkeuringsbezorging, native gedrag, rendering en auth opapprovalCapability.plugin.authis alleen voor inloggen/uitloggen; core leest geen goedkeurings-auth-hooks meer uit dat object.approvalCapability.authorizeActorActionenapprovalCapability.getActionAvailabilityStatezijn de canonieke seam voor goedkeurings-auth.- Gebruik
approvalCapability.getActionAvailabilityStatevoor de beschikbaarheid van goedkeurings-auth in dezelfde chat. - Als je kanaal native exec-goedkeuringen exposeert, gebruik dan
approvalCapability.getExecInitiatingSurfaceStatevoor de status van het initiërende oppervlak/de native client wanneer die verschilt van goedkeurings-auth in dezelfde chat. Core gebruikt die exec-specifieke hook omenabledvandisabledte onderscheiden, te bepalen of het initiërende kanaal native exec-goedkeuringen ondersteunt, en het kanaal op te nemen in fallback-instructies voor native clients.createApproverRestrictedNativeApprovalCapability(...)vult dit in voor het algemene geval. - Gebruik
outbound.shouldSuppressLocalPayloadPromptofoutbound.beforeDeliverPayloadvoor kanaalspecifiek payload-lifecycle-gedrag, zoals het verbergen van dubbele lokale goedkeuringsprompts of het verzenden van type-indicatoren vóór bezorging. - Gebruik
approvalCapability.deliveryalleen voor native goedkeuringsrouting of fallback-onderdrukking. - Gebruik
approvalCapability.nativeRuntimevoor kanaaleigen native goedkeuringsfeiten. Houd dit lazy op hot kanaalentrypoints metcreateLazyChannelApprovalNativeRuntimeAdapter(...), dat je runtimemodule op aanvraag kan importeren terwijl core nog steeds de goedkeuringslifecycle kan samenstellen. - Gebruik
approvalCapability.renderalleen wanneer een kanaal echt aangepaste goedkeuringspayloads nodig heeft in plaats van de gedeelde renderer. - Gebruik
approvalCapability.describeExecApprovalSetupwanneer het kanaal wil dat het antwoord op het disabled-pad uitlegt welke exacte configuratieknoppen nodig zijn om native exec-goedkeuringen in te schakelen. De hook ontvangt{ channel, channelLabel, accountId }; kanalen met benoemde accounts moeten account-gescopete paden renderen, zoalschannels.<channel>.accounts.<id>.execApprovals.*, in plaats van top-level defaults. - Als een kanaal stabiele owner-achtige DM-identiteiten uit bestaande configuratie kan afleiden, gebruik dan
createResolvedApproverActionAuthAdapteruitopenclaw/plugin-sdk/approval-runtimeom same-chat/approvete beperken zonder goedkeuringsspecifieke corelogica toe te voegen. - Als een kanaal native goedkeuringsbezorging nodig heeft, houd de kanaalcode dan gericht op doelnormalisatie plus transport-/presentatiefeiten. Gebruik
createChannelExecApprovalProfile,createChannelNativeOriginTargetResolver,createChannelApproverDmTargetResolverencreateApproverRestrictedNativeApprovalCapabilityuitopenclaw/plugin-sdk/approval-runtime. Zet de kanaalspecifieke feiten achterapprovalCapability.nativeRuntime, idealiter viacreateChannelApprovalNativeRuntimeAdapter(...)ofcreateLazyChannelApprovalNativeRuntimeAdapter(...), zodat core de handler kan samenstellen en eigenaar kan zijn van requestfiltering, routing, dedupe, expiry, Gateway-subscription en meldingen dat iets elders is gerouteerd.nativeRuntimeis opgesplitst in een paar kleinere seams: createChannelNativeOriginTargetResolvergebruikt standaard de gedeelde channel-route matcher voor{ to, accountId, threadId }-doelen. GeeftargetsMatchalleen door wanneer een kanaal providerspecifieke equivalentieregels heeft, zoals Slack timestamp-prefixmatching.- Geef
normalizeTargetForMatchdoor aancreateChannelNativeOriginTargetResolverwanneer het kanaal provider-id’s moet canonicaliseren voordat de standaard routematcher of een aangepastetargetsMatch-callback draait, terwijl het oorspronkelijke doel voor bezorging behouden blijft. GebruiknormalizeTargetalleen wanneer het opgeloste bezorgdoel zelf moet worden gecanonicaliseerd. availability— of het account is geconfigureerd en of een request moet worden afgehandeldpresentation— koppel het gedeelde goedkeuringsviewmodel aan pending/resolved/expired native payloads of finale actiestransport— bereid doelen voor plus verzend/update/verwijder native goedkeuringsberichteninteractions— optionele bind/unbind/clear-action-hooks voor native knoppen of reactiesobserve— optionele hooks voor bezorgdiagnostiek- Als het kanaal runtime-eigen objecten nodig heeft, zoals een client, token, Bolt-app of webhookontvanger, registreer die dan via
openclaw/plugin-sdk/channel-runtime-context. Het generieke runtime-contextregister laat core capability-gedreven handlers bootstrappen vanuit kanaalopstartstatus zonder goedkeuringsspecifieke wrapperlijm toe te voegen. - Grijp alleen naar de lagere-level
createChannelApprovalHandlerofcreateChannelNativeApprovalRuntimewanneer de capability-gedreven seam nog niet expressief genoeg is. - Native goedkeuringskanalen moeten zowel
accountIdalsapprovalKindvia die helpers routeren.accountIdhoudt multi-account-goedkeuringsbeleid gescopet naar het juiste botaccount, enapprovalKindhoudt exec- versus plugingoedkeuringsgedrag beschikbaar voor het kanaal zonder hardcoded branches in core. - Core is nu ook eigenaar van goedkeurings-reroute-meldingen. Kanaalplugins mogen geen eigen vervolgberichten met “approval went to DMs / another channel” verzenden vanuit
createChannelNativeApprovalRuntime; expose in plaats daarvan nauwkeurige origin- en approver-DM-routing via de gedeelde goedkeuringscapabilityhelpers en laat core echte bezorgingen aggregeren voordat er een melding terug naar de initiërende chat wordt geplaatst. - Behoud het soort bezorgd goedkeurings-id end-to-end. Native clients mogen niet gokken of exec- versus plugingoedkeuringsrouting herschrijven vanuit kanaallokale status.
- Verschillende goedkeuringssoorten kunnen bewust verschillende native oppervlakken exposen.
Huidige gebundelde voorbeelden:
- Slack houdt native goedkeuringsrouting beschikbaar voor zowel exec- als plugin-id’s.
- Matrix houdt dezelfde native DM-/kanaalrouting en reactie-UX voor exec- en plugingoedkeuringen, terwijl auth nog steeds per goedkeuringssoort kan verschillen.
createApproverRestrictedNativeApprovalAdapterbestaat nog steeds als compatibiliteitswrapper, maar nieuwe code moet de capability builder verkiezen enapprovalCapabilityop de plugin exposen.
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 en
openclaw/plugin-sdk/reply-chunking wanneer je het bredere parapluoppervlak
niet nodig hebt.
Specifiek voor setup:
openclaw/plugin-sdk/setup-runtimedekt de runtime-veilige setuphelpers: importveilige setup-patchadapters (createPatchedAccountSetupAdapter,createEnvPatchedAccountSetupAdapter,createSetupInputPresenceValidator), lookup-note-uitvoer,promptResolvedAllowFrom,splitSetupEntriesen de gedelegeerde setup-proxybuildersopenclaw/plugin-sdk/setup-adapter-runtimeis de smalle env-bewuste adapter- seam voorcreateEnvPatchedAccountSetupAdapteropenclaw/plugin-sdk/channel-setupdekt de optionele-installatie-setup builders plus een paar setup-veilige primitieven:createOptionalChannelSetupSurface,createOptionalChannelSetupAdapter,
channelEnvVars. Houd runtime-envVars van het kanaal of lokale
constanten alleen voor operatorgerichte tekst.
Als je kanaal kan verschijnen in status, channels list, channels status of
SecretRef-scans voordat de Plugin-runtime start, voeg dan openclaw.setupEntry toe in
package.json. Dat entrypoint moet veilig te importeren zijn in alleen-lezen commandopaden
en moet de kanaalmetadata, setup-veilige configuratie-adapter, statusadapter
en metadata voor kanaalgeheimdoelen retourneren die nodig zijn voor die samenvattingen. Start geen
clients, listeners of transportruntimes vanuit de setup-entry.
Houd ook het importpad van de hoofdentry voor het kanaal smal. Discovery kan de
entry en de kanaalpluginmodule evalueren om capabilities te registreren zonder
het kanaal te activeren. Bestanden zoals channel-plugin-api.ts moeten het kanaal-
pluginobject exporteren zonder setupwizards, transportclients, socketlisteners,
subprocesstarters of servicestartmodules te importeren. Plaats die runtime-
onderdelen in modules die worden geladen vanuit registerFull(...), runtime-setters of luie
capability-adapters.
createOptionalChannelSetupWizard, DEFAULT_ACCOUNT_ID,
createTopLevelChannelDmPolicy, setSetupChannelEnabled en
splitSetupEntries
- gebruik de bredere seam
openclaw/plugin-sdk/setupalleen wanneer je ook de zwaardere gedeelde setup-/configuratiehelpers nodig hebt, zoalsmoveSingleAccountChannelSectionToDefaultAccount(...)
createOptionalChannelSetupSurface(...). De gegenereerde
adapter/wizard faalt gesloten bij configuratieschrijfacties en finalisatie, en hergebruikt
hetzelfde bericht dat installatie vereist is in validatie, finalisatie en docs-linktekst.
Voor andere hete kanaalpaden geef je de voorkeur aan de smalle helpers boven bredere legacy-
oppervlakken:
openclaw/plugin-sdk/account-core,openclaw/plugin-sdk/account-id,openclaw/plugin-sdk/account-resolutionenopenclaw/plugin-sdk/account-helpersvoor multi-accountconfiguratie en fallback naar default-accountopenclaw/plugin-sdk/inbound-envelopeenopenclaw/plugin-sdk/inbound-reply-dispatchvoor inbound route/envelope en record-and-dispatch-bedradingopenclaw/plugin-sdk/messaging-targetsvoor targetparsing/-matchingopenclaw/plugin-sdk/outbound-mediaenopenclaw/plugin-sdk/outbound-runtimevoor het laden van media plus outbound identity-/send-delegates en payloadplanningbuildThreadAwareOutboundSessionRoute(...)uitopenclaw/plugin-sdk/channel-corewanneer een outbound route een explicietereplyToId/threadIdmoet behouden of de huidige:thread:-sessie moet herstellen nadat de basissessiesleutel nog steeds overeenkomt. Provider-Plugins kunnen voorrang, suffixgedrag en normalisatie van thread-id’s overschrijven wanneer hun platform native semantiek voor threadbezorging heeft.openclaw/plugin-sdk/thread-bindings-runtimevoor de lifecycle van thread-bindings en adapterregistratieopenclaw/plugin-sdk/agent-media-payloadalleen wanneer een legacy agent-/media- payloadveldindeling nog vereist isopenclaw/plugin-sdk/telegram-command-configvoor normalisatie van aangepaste Telegram- commando’s, validatie van duplicaten/conflicten en een fallback-stabiel command config-contract
Inbound-vermeldingsbeleid
Houd inbound-vermeldingsafhandeling gesplitst in twee lagen:- bewijsverzameling in eigendom van de Plugin
- gedeelde beleidsevaluatie
openclaw/plugin-sdk/channel-mention-gating voor beslissingen over vermeldingsbeleid.
Gebruik openclaw/plugin-sdk/channel-inbound alleen wanneer je de bredere inbound
helperbarrel nodig hebt.
Goede plek voor plugin-lokale logica:
- reply-to-bot-detectie
- quoted-bot-detectie
- controles op threaddeelname
- uitsluitingen voor service-/systeemberichten
- platform-native caches die nodig zijn om botdeelname te bewijzen
requireMention- expliciet vermeldingsresultaat
- allowlist voor impliciete vermeldingen
- command-bypass
- definitieve oversla-beslissing
- Bereken lokale vermeldingsfeiten.
- Geef die feiten door aan
resolveInboundMentionDecision({ facts, policy }). - Gebruik
decision.effectiveWasMentioned,decision.shouldBypassMentionendecision.shouldSkipin je inbound gate.
api.runtime.channel.mentions stelt dezelfde gedeelde vermeldingshelpers beschikbaar voor
gebundelde kanaal-Plugins die al afhankelijk zijn van runtime-injectie:
buildMentionRegexesmatchesMentionPatternsmatchesMentionWithExplicitimplicitMentionKindWhenresolveInboundMentionDecision
implicitMentionKindWhen en
resolveInboundMentionDecision nodig hebt, importeer dan uit
openclaw/plugin-sdk/channel-mention-gating om te voorkomen dat niet-gerelateerde inbound
runtimehelpers worden geladen.
De oudere resolveMentionGating*-helpers blijven beschikbaar op
openclaw/plugin-sdk/channel-inbound uitsluitend als compatibiliteitsexports. Nieuwe code
moet resolveInboundMentionDecision({ facts, policy }) gebruiken.
Doorloop
Package and manifest
Maak de standaard Plugin-bestanden. Het veld
channel in package.json is
wat dit een kanaal-Plugin maakt. Zie voor het volledige oppervlak voor pakketmetadata
Plugin Setup and Config:configSchema valideert plugins.entries.acme-chat.config. Gebruik dit voor
plugin-eigen instellingen die niet de kanaalaccountconfiguratie zijn. channelConfigs
valideert channels.acme-chat en is de cold-path-bron die door configuratie-
schema, setup en UI-oppervlakken wordt gebruikt voordat de Plugin-runtime laadt.Build the channel plugin object
De interface Gebruik voor kanalen die zowel canonieke DM-sleutels op topniveau als legacy geneste sleutels accepteren de helpers uit
ChannelPlugin heeft veel optionele adapteroppervlakken. Begin met
het minimum — id en setup — en voeg adapters toe wanneer je ze nodig hebt.Maak src/channel.ts:src/channel.ts
plugin-sdk/channel-config-helpers: resolveChannelDmAccess, resolveChannelDmPolicy, resolveChannelDmAllowFrom en normalizeChannelDmPolicy houden account-lokale waarden vóór geërfde rootwaarden. Combineer dezelfde resolver met doctor-reparatie via normalizeLegacyDmAliases, zodat runtime en migratie hetzelfde contract lezen.What createChatChannelPlugin does for you
What createChatChannelPlugin does for you
In plaats van low-level adapterinterfaces handmatig te implementeren, geef je
declaratieve opties door en stelt de builder ze samen:
Je kunt ook ruwe adapterobjecten doorgeven in plaats van de declaratieve opties
als je volledige controle nodig hebt.Raw uitgaande adapters mogen een functie
| Optie | Wat het bedraadt |
|---|---|
security.dm | Gescopeerde DM-beveiligingsresolver uit configuratievelden |
pairing.text | Tekstgebaseerde DM-pairingflow met code-uitwisseling |
threading | Reply-to-mode-resolver (vast, account-gescopeerd of aangepast) |
outbound.attachedResults | Send-functies die resultaatmetadata retourneren (bericht-ID’s) |
chunker(text, limit, ctx) definiëren.
De optionele ctx.formatting bevat formatteringsbeslissingen op bezorgtijdstip
zoals maxLinesPerMessage; pas die toe vóór het verzenden, zodat antwoordthreading
en chunkgrenzen één keer worden opgelost door de gedeelde uitgaande bezorging.
Verzendcontexten bevatten ook replyToIdSource (implicit of explicit)
wanneer een native antwoorddoel is opgelost, zodat payloadhelpers expliciete
antwoordtags kunnen behouden zonder een impliciete eenmalige antwoordslot te gebruiken.Koppel het entrypoint
Maak Plaats CLI-descriptors die eigendom zijn van het kanaal in
index.ts aan:index.ts
registerCliMetadata(...), zodat OpenClaw
ze kan tonen in de root-help zonder de volledige kanaalruntime te activeren,
terwijl normale volledige loads nog steeds dezelfde descriptors oppakken voor echte commandoregistratie.
Houd registerFull(...) voor werk dat alleen bij runtime hoort.
Als registerFull(...) Gateway-RPC-methoden registreert, gebruik dan een
Plugin-specifiek prefix. Core-beheernamespaces (config.*,
exec.approvals.*, wizard.*, update.*) blijven gereserveerd en worden altijd
omgezet naar operator.admin.
defineChannelPluginEntry handelt de splitsing van registratiemodus automatisch af. Zie
Entrypoints voor alle
opties.Voeg een setup-entry toe
Maak OpenClaw laadt dit in plaats van de volledige entry wanneer het kanaal is uitgeschakeld
of niet is geconfigureerd. Dit voorkomt dat zware runtimecode wordt geladen tijdens setupflows.
Zie Setup en Config voor details.Gebundelde werkruimtekanelen die setup-veilige exports opsplitsen in sidecar-modules
kunnen
setup-entry.ts aan voor lichtgewicht laden tijdens onboarding:setup-entry.ts
defineBundledChannelSetupEntry(...) uit
openclaw/plugin-sdk/channel-entry-contract gebruiken wanneer ze ook een
expliciete runtime-setter voor setuptijd nodig hebben.Verwerk inkomende berichten
Je Plugin moet berichten van het platform ontvangen en ze doorsturen naar
OpenClaw. Het gebruikelijke patroon is een Webhook die het verzoek verifieert en
het doorstuurt via de inkomende handler van je kanaal:
Verwerking van inkomende berichten is kanaalspecifiek. Elke kanaal-Plugin bezit
zijn eigen inkomende pipeline. Bekijk gebundelde kanaal-Plugins
(bijvoorbeeld het Microsoft Teams- of Google Chat-Plugin-pakket) voor echte patronen.
Test
Schrijf colocated tests in Zie Testen voor gedeelde testhelpers.
src/channel.test.ts:src/channel.test.ts
Bestandsstructuur
Geavanceerde onderwerpen
Threadingopties
Vaste, account-gescopeerde of aangepaste antwoordmodi
Integratie van berichtentool
describeMessageTool en actiedetectie
Doelresolutie
inferTargetChatType, looksLikeId, resolveTarget
Runtimehelpers
TTS, STT, media, subagent via api.runtime
Sommige gebundelde helperseams bestaan nog steeds voor onderhoud en
compatibiliteit van gebundelde Plugins. Ze zijn niet het aanbevolen patroon voor nieuwe kanaal-Plugins;
gebruik liever de generieke subpaden voor kanaal/setup/antwoord/runtime uit het gemeenschappelijke SDK-oppervlak,
tenzij je die gebundelde Plugin-familie rechtstreeks onderhoudt.
Volgende stappen
- Provider-Plugins — als je Plugin ook modellen levert
- SDK-overzicht — volledige referentie voor subpath-imports
- SDK-testen — testhulpprogramma’s en contracttests
- Plugin-manifest — volledig manifestschema