Plugin maintainer reference
API für ausgehende Kanalnachrichten
Channel-Plugins stellen das Verhalten für ausgehende Nachrichten über
openclaw/plugin-sdk/channel-outbound bereit. Verwenden Sie
openclaw/plugin-sdk/channel-inbound für die Orchestrierung von Empfang, Kontext und Dispatch.
Der Core ist zuständig für Warteschlangen, Dauerhaftigkeit, den dauerhaften Ingress-Monitor und Drain
(createChannelIngressMonitor, createChannelIngressDrain und
openChannelIngressDrain), die generische Wiederholungsrichtlinie, den Lebenszyklus der Turn-Übernahme
(turnAdoptionLifecycle / bindIngressLifecycleToReplyOptions), Hooks,
Empfangsbestätigungen und das gemeinsame Tool message. Das Plugin ist zuständig für native
Aufrufe zum Senden/Bearbeiten/Löschen, Zielnormalisierung, plattformspezifische Threads, ausgewählte
Zitate, Benachrichtigungs-Flags, Kontostatus, Ingress-Prüfung und Payload-
Codierung, Lane-Schlüssel, Prädikate für nicht wiederholbare Fehler, optionale Supersede-
Autorisierung und plattformspezifische Nebeneffekte.
Dauerhafte Ingress-Monitore
Verwenden Sie createChannelIngressMonitor(...), wenn ein Channel akzeptierte
Transportereignisse vor dem Dispatch dauerhaft speichern muss. Es kombiniert eine Channel-Ingress-Warteschlange und einen Drain
mit dem gemeinsamen Lebenszyklus für Zulassung, Polling, Bereinigung, Zustellung und Herunterfahren.
Verwenden Sie das niedriger angesiedelte createChannelIngressDrain(...) nur, wenn der Transport
einen wesentlich anderen Zulassungs- oder Pump-Vertrag besitzt.
Folgende Optionen sind erforderlich:
| Option | Vertrag |
|---|---|
queue |
Ein ChannelIngressQueue oder eine verzögerte Factory, die die kontobezogene Warteschlange öffnet. |
inspect(raw, context) |
Gibt die stabile eventId und die serialisierte laneKey zurück oder null für ein ignoriertes Ereignis. Die Fakten zum Claim-Zeitpunkt müssen mit der dauerhaft gespeicherten ID und Lane übereinstimmen. |
payload |
Stellt die Payload-Version sowie die Serialisierung/Deserialisierung des Inhalts bereit. Verwenden Sie storage: "raw-event" für den standardmäßigen String-Umschlag { version, rawEvent } oder stellen Sie benutzerdefinierte Encode-/Decode-Callbacks für eine vorhandene Channel-spezifische Struktur bereit. createClaimError klassifiziert ungültige Versionen oder eine geänderte Identität. |
deliver(raw, lifecycle, claim) |
Führt den Dispatch eines decodierten Ereignisses aus und empfängt den vollständigen Übernahmelebenszyklus. Es kann completed, deferred, failed-retryable oder nichts zurückgeben. |
pollIntervalMs |
Plant Wiederherstellungs-/Drain-Polls, während der Monitor ausgeführt wird. |
retention |
Legt den Bereinigungsrhythmus sowie TTLs und Eintragsobergrenzen für abgeschlossene/fehlgeschlagene Einträge fest. |
Der Monitor serialisiert Zulassungen, damit der Append-Backoff die Reihenfolge einer Lane nicht umkehren kann. Die
standardmäßigen begrenzten Append-Verzögerungen betragen 0, 100 und 300 ms; nach ihrer Ausschöpfung wird
der Transport-Callback abgelehnt, statt ein Ereignis zu dispatchen, das nicht
dauerhaft gespeichert wurde. Zum Claim-Zeitpunkt decodiert der Monitor die versionierte Payload, führt inspect erneut aus und
lehnt eine nicht übereinstimmende ID oder Lane vor der Zustellung ab.
deliver empfängt onAdopted, onDeferred, onAdoptionFinalizing,
onAbandoned und abortSignal. Eine Rückgabe ohne explizite Übergabe markiert ein
terminales Ereignis ohne Dispatch als übernommen. admission ist immer exclusive. Eine
verzögerte Übergabe hält den Claim aufrecht, während Herunterfahren oder Abbruch nicht übernommene
Arbeit weiterhin wiederholbar lässt. Der Monitor verfolgt die Zustellung unabhängig vom Abschluss des Claims,
da die Übernahme eine Zeile mit einem Tombstone versehen kann, bevor das Zustellungs-Promise des Channels
zurückgegeben wird.
Zu den optionalen Einstellungen gehören benutzerdefinierte Append-Verzögerungen, ein Optionsblock drain für
erweiterte Drain-Reihenfolge, Parallelität und Wiederholungsrichtlinie, ein externes abortSignal, eine
Uhr, die Meldung von Pump-Fehlern, eine Factory für Fehler im gestoppten Zustand und eine Zulassungsrichtlinie.
Der zurückgegebene Monitor stellt admit, start, pause, stop, waitForIdle,
isRunning und isStopped bereit. stop schließt zunächst akzeptierte Zulassungen ab,
bricht dann den Drain ab und gibt ihn frei, wartet auf die Pump und aktive Zustellungen und
gibt ihn erneut frei, um das Race bei der verzögerten Erstellung zu schließen.
Belassen Sie transportspezifische Schwärzung, Validierung des Roh-Umschlags, Klassifizierung als nicht wiederholbar
und die dauerhaft gespeicherte Payload-Struktur im Plugin. Webhook-Transporte
sollten erst eine Bestätigung senden, nachdem admit aufgelöst wurde; Transporte ohne Wiederholungsmöglichkeit sollten
die Ausschöpfung dauerhafter Append-Versuche melden, statt stillschweigend zu dispatchen.
Adapter
Die meisten Plugins definieren einen message-Adapter:
defineChannelMessageAdapter, createMessageReceiptFromOutboundResults,} from "openclaw/plugin-sdk/channel-outbound"; export const demoMessageAdapter = defineChannelMessageAdapter({ id: "demo", durableFinal: { capabilities: { text: true, replyTo: true, thread: true, messageSendingHooks: true, }, }, send: { text: async ({ cfg, to, text, accountId, replyToId, threadId, signal }) => { const sent = await sendDemoMessage({ cfg, to, text, accountId: accountId ?? undefined, replyToId: replyToId ?? undefined, threadId: threadId == null ? undefined : String(threadId), signal, }); return { receipt: createMessageReceiptFromOutboundResults({ results: [{ channel: "demo", messageId: sent.id, conversationId: to }], kind: "text", threadId: threadId == null ? undefined : String(threadId), replyToId: replyToId ?? undefined, }), }; }, },});Deklarieren Sie nur Fähigkeiten, die der native Transport tatsächlich erhält. Decken Sie jede deklarierte Fähigkeit für Senden, Empfangsbestätigungen, Live-Vorschau und Empfangsbestätigung mit den aus diesem Unterpfad exportierten Vertragshilfen ab.
Unterdrückung ausgehender Echos
Wenn eine Plattform die eigene ausgehende Nachricht des Plugins erneut als eingehend zustellen kann, rufen Sie recordOutboundMessageIdentity(...) mit Channel, Konto, Konversation und einer stabilen Plattformnachrichten- oder Quellidentität auf. Der gemeinsame Pfad für eingehende Turns verwirft übereinstimmende Identitäten innerhalb eines begrenzten Zeitfensters von 30 Sekunden vor der Sitzungsaufzeichnung oder dem Agent-Dispatch; eine Quellidentität kann vor dem Senden reserviert oder beim Entfernen einer Channel-Route aktualisiert werden, um Zustellungs-Races zu schließen. isRecentOutboundMessageIdentity(...) stellt dieselbe Abfrage für Channel-Diagnosen und Tests bereit. Pflegen Sie für dieselbe stabile Identität keinen parallelen Channel-lokalen TTL-Cache.
Klartextbereinigung
Verwenden Sie sanitizeForPlainText(...), wenn ein Adapter für ausgehende Nachrichten die
unterstützten HTML-Formatierungs-Tags in leichtgewichtige Textauszeichnung umwandeln muss. Standardmäßig bleiben
die vorhandenen chatartigen Markierungen für Fettdruck und Durchstreichung erhalten. Übergeben Sie
{ style: "markdown" } nur, wenn der Channel das Ergebnis erneut als Markdown parst:
const chatText = sanitizeForPlainText(text);const markdownText = sanitizeForPlainText(text, { style: "markdown" });Der Markdown-Stil verwendet **bold** und ~~strikethrough~~; Kursivschrift und Inline-
Code behalten in beiden Stilen _italic_ und Backtick-Markierungen bei. Wählen Sie den Stil an
der Channel-Grenze aus, statt Markierungstext nach der Bereinigung umzuschreiben.
Zustellungsnachweis
Ein MessageReceipt zeichnet das von einem Channel-Adapter zurückgegebene Ergebnis auf. Konkrete
Plattformnachrichten-IDs zeigen, dass der Sendeweg der Plattform die
Nachricht akzeptiert hat; sie beweisen nicht, dass das Gerät eines Empfängers sie angezeigt oder gelesen hat.
Empfangsbestätigungen ohne Plattformnachrichten-IDs sind lediglich lokale Empfangsmetadaten.
Channels mit Lesebestätigungen oder einem Gerätezustellungsstatus sollten diese Fakten
über einen separaten Channel-spezifischen Pfad verfolgen.
Wenn ein Channel-Adapter nachweisen kann, dass die Wiederholung eines Fehlers keinen
für den Empfänger sichtbaren Sendevorgang duplizieren kann und kein finalisierungsfähiger Aufruf begonnen hat, lösen Sie
new PlatformMessageNotDispatchedError("...", { cause: error }) aus
openclaw/plugin-sdk/error-runtime aus. Der Core kann dann veraltete Nachweise für Sendeversuche
löschen und den Intent in der Warteschlange sicher wiederholen. Nur der Adapter, dem die
endgültige Dispatch-Grenze gehört, darf diese Zusicherung abgeben. Verwenden Sie die Markierung niemals, nachdem ein
Finalisierungs-/Sendeaufruf begonnen hat oder ein mehrdeutiges Ergebnis zurückgibt; eine falsche Markierung kann
Nachrichten duplizieren.
Vorhandene Adapter für ausgehende Nachrichten
Wenn der Channel bereits über einen kompatiblen outbound-Adapter verfügt, leiten Sie den
Nachrichtenadapter daraus ab, statt den Sendecode zu duplizieren:
export const messageAdapter = createChannelMessageAdapterFromOutbound({ id: "demo", outbound, durableFinal: { capabilities: { text: true, media: true, }, },});Dauerhafte Sendevorgänge
Runtime-Sendehilfen befinden sich ebenfalls unter channel-outbound:
sendDurableMessageBatch(...)withDurableMessageSendContext(...)deliverInboundReplyWithMessageSendContext(...)- Hilfen für Draft-Streaming/Fortschritt wie
resolveChannelDraftStreamingChunking(...)
sendDurableMessageBatch(...) gibt genau ein explizites Ergebnis zurück:
| Ergebnis | Bedeutung |
|---|---|
sent |
Mindestens eine sichtbare Plattformnachricht wurde vom Sendeweg der Plattform akzeptiert. |
suppressed |
Keine Plattformnachricht sollte als fehlend behandelt werden. |
partial_failed |
Mindestens eine Plattformnachricht wurde akzeptiert, bevor eine spätere Payload oder ein Nebeneffekt fehlschlug. |
failed |
Es wurde keine Plattform-Empfangsbestätigung erzeugt. |
Verwenden Sie payloadOutcomes, wenn ein Batch gesendete, unterdrückte und fehlgeschlagene
Payloads mischt. Leiten Sie die Hook-Abbrechung nicht aus einem leeren veralteten
Direktzustellungsergebnis ab.
Zulassung verzögerter Zustellungen
Verwenden Sie message.durableFinal.admitDeferredDelivery(...), wenn ein aufgelöstes Konto
vom Core verwaltete ausgehende oder verzögerte Zustellungen nicht sicher akzeptieren kann. Der Core ruft
diesen Hook synchron vor aktiver ausgehender Arbeit auf, einschließlich Pfaden, welche die
dauerhafte Speicherung in der Warteschlange überspringen, und erneut vor der Wiedergabe eines wiederhergestellten Intents. Der Kontext
enthält cfg, channel, to, accountId und ein phase mit live oder
recovery.
Geben Sie { status: "allowed" } zurück, um fortzufahren. Geben Sie
{ status: "permanent_rejection", reason } zurück, wenn die Zustellung weder
dauerhaft gespeichert noch direkt gesendet oder erneut wiedergegeben werden darf. Eine aktive Ablehnung schlägt vor der Erstellung der Warteschlange,
Nachrichten-Hooks oder Plattformarbeit fehl. Eine Ablehnung bei der Wiederherstellung markiert den
Warteschlangeneintrag als fehlgeschlagen und überspringt Abgleich und Wiedergabe. Wird der Hook weggelassen,
gilt die Zustellung als zulässig.
Der Hook ist eine synchrone Zulassungsentscheidung, kein Sendepfad. Lesen Sie nur
bereits geladene Konfiguration oder bereits geladenen Laufzeitstatus; führen Sie keine Netzwerk-, Dateisystem- oder
sonstigen asynchronen E/A-Vorgänge aus. Vertragstests sollten beide Phasen und beide
Ergebnisvarianten über ChannelMessageDurableFinalAdapter aus
openclaw/plugin-sdk/channel-outbound abdecken.
Kompatibilitäts-Dispatch
Stellen Sie den Dispatch eingehender Antworten über dispatchChannelInboundReply(...)
aus channel-inbound zusammen. Belassen Sie die Plattformzustellung im Zustelladapter; verwenden Sie
channel-outbound für Nachrichtenadapter, persistente Sendevorgänge, Empfangsbestätigungen, Live-
Vorschau und Optionen der Antwort-Pipeline.