components, Slack
blocks, Telegram buttons, Teams card of Feishu card toe aan de gedeelde
berichttool. Dit zijn rendereruitvoeren die eigendom zijn van de kanaalplugin.
Contract
Pluginauteurs importeren het openbare contract uit:action.type: "command"voert een native slash-opdracht uit via het opdrachtpad van de kern. Gebruik dit voor ingebouwde opdrachtknoppen en menu’s.action.type: "callback"voert ondoorzichtige plugingegevens door het interactiepad van het kanaal. Kanaalplugins mogen callbackgegevens niet opnieuw interpreteren als slash-opdrachten.action.type: "approval"identificeert één duurzame goedkeuring door een operator, het expliciete typeexecofpluginen de gevraagde beslissing. Kanaalplugins coderen die actie in een transportspecifieke privé-callback en verwerken deze via de goedkeuringsservice; ze mogen geen/approve-opdrachttekst parseren of het type uit de ID afleiden.action.type: "question"identificeert één keuze voor een actieve, tijdens runtime opgesteldeask_user-vraag. Net alsapprovalis dit een OpenClaw-runtimeactie; agents en plugins mogen geen vraag-ID’s genereren. Telegram, Discord en Slack zetten deze om in transportspecifieke privé-native callbacks en verwerken de keuze via de Gateway. Wanneer de vraag is beantwoord, verlopen of geannuleerd, bewerken die kanalen het afgeleverde bericht, verwijderen ze de acties en voegen ze de eindstatus toe. WhatsApp, Signal en iMessage renderen maximaal vier enkelvoudige selectiekeuzes als reacties van1️⃣tot en met4️⃣. Andere vraagvormen worden teruggebracht tot labeltekst en de gebruiker kan antwoorden met een bericht in platte tekst.action.type: "url"opent een normale link.action.type: "web-app"start een kanaalspecifieke native webapp. Stelurlin voor een URL-gebaseerde app ofwidgetIdvoor een door OpenClaw gehoste widget waarvan het startmechanisme eigendom is van het kanaal; ten minste één ervan is vereist. Wanneer beide aanwezig zijn, kan een kanaal de voorkeur geven aan het native startmechanisme voor gehoste widgets en de URL gebruiken waar dat mechanisme niet beschikbaar is.valueis de verouderde ondoorzichtige callbackwaarde. Nieuwe besturingselementen moetenactiongebruiken, zodat kanaalplugins opdrachten en callbacks kunnen omzetten zonder op basis van tekst te hoeven gokken.url,webAppenweb_appblijven geaccepteerd als verouderde invoer aan de grens. Normalisatiefuncties behouden deze velden, zodat renderers onderscheid kunnen maken tussen uitgebrachte verouderde semantiek en expliciete getypeerde acties. Nieuwe producenten moetenactiongebruiken.labelis vereist en wordt ook gebruikt in de tekstuele fallback.styleis adviserend. Renderers moeten niet-ondersteunde stijlen omzetten naar een veilige standaardwaarde en het verzenden niet laten mislukken.priorityis optioneel. Wanneer een kanaal actielimieten bekendmaakt en besturingselementen moeten worden verwijderd, behoudt de kern eerst de knoppen met een hogere prioriteit en de oorspronkelijke volgorde van knoppen met dezelfde prioriteit. Wanneer alle besturingselementen passen, blijft de opgestelde volgorde behouden.disabledis optioneel. Kanalen moeten zich aanmelden metsupportsDisabled; anders brengt de kern het uitgeschakelde besturingselement terug tot niet-interactieve fallbacktekst. Een uitgeschakelde knop wordt in fallbacktekst altijd alleen als label weergegeven, zelfs wanneer deze eencommand-actie bevat.reusableis optioneel. Kanalen die herbruikbare native callbacks ondersteunen, mogen de actie na een geslaagde interactie beschikbaar houden. Gebruik dit voor herhaalbare of idempotente acties zoals vernieuwen, inspecteren of meer details; laat dit uitgeschakeld voor normale eenmalige goedkeuringen en destructieve acties.
options[].actionaccepteert alleencommandofcallback; goedkeurings- en linkacties zijn alleen voor knoppen.options[].valueis de verouderde geselecteerde toepassingswaarde.placeholderis adviserend en kan worden genegeerd door kanalen zonder native selectieondersteuning.- Als een kanaal geen selecties ondersteunt, vermeldt de fallbacktekst de labels.
pievereist positieve segmentwaarden.bar,areaenlinegebruiken één geordendecategories-array. Elke reeks levert precies één eindige waarde per categorie, in dezelfde volgorde.- Categorielabels en reeksnamen moeten uniek zijn. Ongeldige of onvolledige grafiekblokken worden tijdens normalisatie verwijderd in plaats van de gegevens stilzwijgend te wijzigen.
- Native grafiekweergave vereist aanmelding via
presentationCapabilities.charts. Andere kanalen ontvangen de grafiektitel, assen, categorieën, reeksen en waarden als deterministische tekst. Dit is ook de toegankelijkheidsfallback.
-
captionis een vereiste korte kop.headersmoet ten minste één uniek, niet-leeg kolomlabel bevatten. -
rowsmoet ten minste één rij bevatten. Elke rij moet precies één cel per kop hebben en elke cel moet een niet-lege tekenreeks of een eindig getal zijn. -
rowHeaderColumnIndexis een optionele op nul gebaseerde index die de kolom identificeert waarvan de cellen door native renderers als rijkoppen moeten worden weergegeven. - Tabelnormalisatie is atomair. Bij een ongeldig bijschrift, een ongeldige kop, rijbreedte, cel of rijkopindex wordt het tabelblok verwijderd in plaats van dat de gegevens worden afgekapt of hersteld.
-
Native tabelweergave vereist aanmelding via
presentationCapabilities.tables. Andere kanalen ontvangen het bijschrift en elke rij als deterministische lineaire tekst, waarbij interne witruimte wordt samengevouwen:
report-discriminator. Stel een rapport samen uit title,
tone, text, context, chart, table en actieblokken. Hierdoor blijft elk
blok afzonderlijk renderbaar en krijgt het volledige rapport dezelfde
deterministische tekstuele fallback.
Voorbeelden voor producenten
Eenvoudige kaart:Renderercontract
Kanaalplugins declareren rendererondersteuning op hun uitgaande adapter:limits beschrijven de generieke envelop die de kern kan aanpassen voordat de
renderer wordt aangeroepen:
Kernrenderflow
Op het canonieke uitgaande pad dat door de CLI en standaardberichtacties wordt gebruikt, doet de kern het volgende:- Normaliseert de presentatiepayload.
- Bepaalt de uitgaande adapter van het doelkanaal.
- Leest
presentationCapabilities. - Past generieke capability-limieten toe, zoals het aantal acties, de labellengte en
het aantal selectieopties, wanneer de adapter deze adverteert. Grafiek- en tabelblokken
worden deterministische tekst, tenzij de adapter respectievelijk expliciet
charts: trueoftables: trueadverteert. - Roept
renderPresentationaan wanneer de adapter de payload kan renderen. - Valt terug op conservatieve tekst wanneer de adapter ontbreekt of niet kan renderen.
- Verzendt de resulterende payload via het normale bezorgingspad van het kanaal.
- Past bezorgingsmetadata zoals
delivery.pintoe na het eerste succesvol verzonden bericht.
ReplyPayload rechtstreeks verwerken,
moeten ofwel dat canonieke pad volgen, of hetzelfde presentatiealternatief materialiseren
voordat de payload wordt teruggebracht tot platte tekst/media.
De kern is verantwoordelijk voor het terugvalgedrag, zodat producenten kanaalonafhankelijk kunnen blijven. Kanaalplugins
zijn verantwoordelijk voor native rendering en interactieafhandeling.
Degradatieregels
De presentatie moet veilig kunnen worden verzonden via beperkte kanalen. Alternatieve tekst bevat:titleals eerste regeltext-blokken als normale alinea’scontext-blokken als compacte contextregelsdivider-blokken als visueel scheidingsteken- knoplabels, inclusief URL’s voor linkknoppen
- labels van selectieopties
- grafiektitel, -type, assen, categorieën, reeksen en waarden
- tabelbijschrift, kopteksten en elke rijwaarde
Zichtbaarheid van knopwaarden in het alternatief
Wanneer een kanaal geen interactieve bedieningselementen kan renderen, vallen knop- en selectiewaarden terug op platte tekst. Het terugvalgedrag behoudt de bruikbaarheid en houdt tegelijkertijd ondoorzichtige callbackgegevens privé:- Acties van het type
commandworden gerenderd alslabel: `command`, zodat gebruikers de opdracht kunnen kopiëren en handmatig in de kanaalinvoer kunnen uitvoeren. - Acties van het type
callbacken verouderdevalue-velden worden uitsluitend als label gerenderd. De ondoorzichtige callbackwaarde wordt niet weergegeven in de alternatieve tekst. - Acties van het type
approvalworden uitsluitend als label gerenderd. Goedkeurings-ID’s en beslissingen zijn transportgegevens en worden niet via generieke scalaire helpers of alternatieve tekst weergegeven. url-acties, door URL’s ondersteundeweb-app-acties en verouderdeurl/webApp/web_app-invoer renderen de URL-tekst naast het knoplabel, omdat de URL voor de gebruiker zichtbaar is. Acties die uitsluitend voor gehoste widgets zijn bedoeld, worden alleen als label weergegeven op kanalen zonder native widgetstart.- Selectieopties worden uitsluitend als label gerenderd. De onderliggende optiewaarde wordt niet weergegeven in de alternatieve tekst.
- Telegram met uitgeschakelde inlineknoppen verzendt het tekstalternatief.
- Een kanaal zonder selectieondersteuning vermeldt selectieopties als tekst.
- Een kanaal zonder native grafiekondersteuning vermeldt de grafiekgegevens als tekst.
- Een kanaal zonder native tabelondersteuning vermeldt elke tabelrij als tekst.
- Een knop met alleen een URL wordt een native linkknop of een alternatieve URL-regel.
- Optionele fouten bij vastzetten laten het bezorgde bericht niet mislukken.
delivery.pin.required: true; als vastzetten als
verplicht is aangevraagd en het kanaal het verzonden bericht niet kan vastzetten, meldt de bezorging een fout.
Providertoewijzing
Huidige gebundelde renderers:
Compatibiliteit met providernative payloads is een overgangsvoorziening voor bestaande
antwoordproducenten. Dit is geen reden om nieuwe gedeelde native velden toe te voegen.
Presentation versus InteractiveReply
InteractiveReply is de oudere interne subset die door goedkeurings- en interactiehelpers wordt gebruikt.
Deze ondersteunt:
- tekst
- knoppen
- selecties
MessagePresentation is het canonieke gedeelde verzendcontract. Dit voegt het volgende toe:
- titel
- toon
- context
- scheidingsteken
- grafiek
- tabel
- knoppen met alleen een URL
- generieke bezorgingsmetadata via
ReplyPayload.delivery
openclaw/plugin-sdk/interactive-runtime bij het overbruggen van oudere
code:
MessagePresentation rechtstreeks accepteren of produceren. Bestaande
interactive-payloads zijn een verouderde subset van presentation; runtime-
ondersteuning blijft beschikbaar voor oudere producenten.
Niet-verouderde helpers die nuttig zijn om te kennen:
normalizeMessagePresentation(raw)/hasMessagePresentationBlocks(value)valideren en zetten een ongetypeerde payload (bijvoorbeeld JSON van de CLI-vlag--presentation) om naarMessagePresentation.isMessagePresentationInteractiveBlock(block)beperkt een blok tot de uniebuttons|select.resolveMessagePresentationButtonAction(button)enresolveMessagePresentationOptionAction(option)retourneren de canonieke getypeerde actie en accepteren daarbij verouderde grensvelden. Een explicieteactionheeft altijd voorrang.resolveMessagePresentationActionValue(action)/resolveMessagePresentationControlValue(control)lezen uitsluitend scalaire opdracht-/callbackwaarden. Een niet-scalaire canonieke actie valt nooit terug op een verouderde schaduw-value, zodat goedkeurings-ID’s en linkdoelen getypeerd blijven.renderMessagePresentationChartFallbackText(block)/renderMessagePresentationTableFallbackText(block)geven één gestructureerd gegevensblok weer als deterministische tekst voor kanaalspecifieke fallbackpaden.
InteractiveReply*-typen en conversiehelpers zijn in de SDK gemarkeerd als
@deprecated:
InteractiveReply,InteractiveReplyBlock,InteractiveReplyButtonenInteractiveReplyOptionnormalizeInteractiveReply(...)hasInteractiveReplyBlocks(...)interactiveReplyToPresentation(...)presentationToInteractiveReply(...)presentationToInteractiveControlsReply(...)resolveInteractiveTextFallback(...)reduceInteractiveReply(...)
presentationToInteractiveReply(...) en
presentationToInteractiveControlsReply(...) blijven beschikbaar als rendererbruggen
voor verouderde kanaalimplementaties. Nieuwe producercode hoort ze niet aan te roepen;
stuur presentation en laat de aanpassing door de kern/het kanaal de weergave afhandelen.
Goedkeuringshelpers hebben ook presentatiegerichte vervangingen:
- gebruik
buildApprovalPresentation(...)in plaats vanbuildApprovalInteractiveReply(...) - gebruik
buildExecApprovalPresentation(...)in plaats vanbuildExecApprovalInteractiveReply(...)
buildTypedApprovalPresentation(...),
buildTypedExecApprovalPendingReplyPayload(...) of
buildTypedPluginApprovalPendingReplyPayload(...) te gebruiken, zodat transports een
expliciete approval-actie ontvangen in plaats van semantiek af te leiden uit /approve-tekst.
renderMessagePresentationFallbackText(...) retourneert een lege tekenreeks voor
presentatieblokken die geen tekstuele fallback hebben, zoals een presentatie met
alleen een scheidingslijn. Transports die een niet-lege verzendinhoud vereisen, kunnen
emptyFallback doorgeven om te kiezen voor een minimale inhoud zonder het standaard
fallbackcontract te wijzigen.
Vastzetten bij aflevering
Vastzetten is afleveringsgedrag, geen presentatie. Gebruikdelivery.pin in plaats van
providerspecifieke velden zoals channelData.telegram.pin.
Semantiek:
pin: truezet het eerste succesvol afgeleverde bericht vast.pin.notifyis standaardfalse.pin.requiredis standaardfalse.- Optionele fouten bij het vastzetten leiden tot degradatie en laten het verzonden bericht intact.
- Verplichte fouten bij het vastzetten laten de aflevering mislukken.
- Bij berichten in delen wordt het eerste afgeleverde deel vastgezet, niet het laatste deel.
pin, unpin en pins blijven bestaan voor bestaande
berichten waarvoor de provider deze bewerkingen ondersteunt.
Checklist voor Plugin-auteurs
- Declareer
presentationvanuitdescribeMessageTool(...)wanneer het kanaal semantische presentatie kan weergeven of veilig kan degraderen. - Voeg
presentationCapabilitiestoe aan de uitgaande runtime-adapter. - Implementeer
renderPresentationin runtimecode, niet in de Plugin-installatiecode van het besturingsvlak. - Houd native UI-bibliotheken buiten intensief gebruikte installatie-/cataloguspaden.
- Declareer generieke capaciteitslimieten op
presentationCapabilities.limitswanneer ze bekend zijn. - Handhaaf de uiteindelijke platformlimieten in de renderer en tests.
- Voeg fallbacktests toe voor niet-ondersteunde grafieken, tabellen, knoppen, selecties, URL-
knoppen, duplicatie van titel/tekst en gemengde verzendingen met
messagepluspresentation. - Voeg ondersteuning voor vastzetten bij aflevering uitsluitend toe via
deliveryCapabilities.pinenpinDeliveredMessagewanneer de provider de ID van het verzonden bericht kan vastzetten. - Stel geen nieuwe providerspecifieke kaart-/blok-/component-/knopvelden beschikbaar via het gedeelde schema voor berichtacties.