Ця сторінка описує цільовий дизайн для заміни розрізнених допоміжних засобів обробки channel turn, надсилання відповідей, preview streaming та вихідної доставки єдиним надійним життєвим циклом повідомлення. Коротка версія:Documentation Index
Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
- Основні примітиви мають бути receive і send, а не reply.
- Відповідь є лише відношенням у вихідному повідомленні.
- Turn є зручністю для обробки вхідних даних, а не власником доставки.
- Надсилання має базуватися на контексті:
begin, render, preview або stream, final send, commit, fail. - Отримання також має базуватися на контексті: normalize, dedupe, route, record, dispatch, platform ack, fail.
- Публічний plugin SDK має звестися до однієї невеликої поверхні channel-message.
Проблеми
Поточний стек каналів виріс із кількох обґрунтованих локальних потреб:- Прості вхідні адаптери використовують
runtime.channel.turn.run. - Розширені адаптери використовують
runtime.channel.turn.runPrepared. - Застарілі допоміжні засоби використовують
dispatchInboundReplyWithBase,recordInboundSessionAndDispatchReply, допоміжні засоби reply payload, reply chunking, reply references і outbound runtime helpers. - Preview streaming живе в диспетчерах, специфічних для каналів.
- Надійність фінальної доставки додається навколо наявних шляхів reply payload.
Цілі
- Один життєвий цикл ядра для всіх шляхів отримання й надсилання channel message.
- Надійні фінальні надсилання за замовчуванням у новому життєвому циклі повідомлення після того, як адаптер оголосить replay-safe поведінку.
- Спільна семантика preview, edit, stream, finalization, retry, recovery і receipt.
- Невелика поверхня plugin SDK, яку сторонні plugins можуть вивчити й підтримувати.
- Сумісність для наявних викликів
channel.turnпід час міграції. - Чіткі точки розширення для нових можливостей каналів.
- Без специфічних для платформи гілок у ядрі.
- Без token-delta повідомлень каналів. Channel streaming залишається доставкою message preview, edit, append або completed block.
- Структуровані метадані походження з OpenClaw для операційного/системного виводу, щоб видимі збої gateway не входили повторно в спільні кімнати з увімкненими ботами як нові prompts.
Нецілі
- Не видаляти
runtime.channel.turn.*на першому етапі. - Не змушувати кожен канал до однакової нативної транспортної поведінки.
- Не навчати ядро Telegram topics, Slack native streams, Matrix redactions, Feishu cards, QQ voice або Teams activities.
- Не публікувати всі внутрішні допоміжні засоби міграції як стабільний SDK API.
- Не робити так, щоб повторні спроби повторно відтворювали завершені неідемпотентні операції платформи.
Еталонна модель
Vercel Chat має хорошу публічну ментальну модель:ChatThreadChannelMessage- методи адаптера, як-от
postMessage,editMessage,deleteMessage,stream,startTypingі отримання історії - адаптер стану для dedupe, locks, queues і persistence
- Надійні наміри вихідного надсилання перед прямими транспортними викликами.
- Явні контексти надсилання з begin, commit і fail.
- Контексти отримання, які знають політику platform ack.
- Квитанції, які переживають перезапуск і можуть керувати edits, deletes, recovery та duplicate suppression.
- Менший публічний SDK. Вбудовані plugins можуть використовувати внутрішні runtime helpers, але сторонні plugins мають бачити один узгоджений message API.
- Поведінка, специфічна для агента: sessions, transcripts, block streaming, tool progress, approvals, media directives, silent replies і group mention history.
thread.post() для OpenClaw недостатньо. Вони приховують
межу транзакції, яка визначає, чи можна відновити надсилання.
Модель ядра
Новий домен має жити у внутрішньому просторі імен ядра, наприкладsrc/channels/message/*.
Він має чотири поняття:
receive володіє вхідним життєвим циклом.
send володіє вихідним життєвим циклом.
live володіє preview, edit, progress і stream state.
state володіє durable intent storage, receipts, idempotency, recovery, locks і
dedupe.
Терміни повідомлень
Повідомлення
Нормалізоване повідомлення є платформонейтральним:Ціль
Ціль описує, де живе повідомлення:Відношення
Відповідь є відношенням, а не коренем API:Походження
Походження описує, хто створив повідомлення і як OpenClaw має обробляти echoes цього повідомлення. Воно відокремлене від relation: повідомлення може бути відповіддю користувачу і водночас бути операційним виводом походження OpenClaw.allowBots увімкнено.
Квитанція
Квитанції є першокласними:Контекст отримання
Отримання не має бути простим викликом допоміжної функції. Ядру потрібен контекст, який знає dedupe, routing, session recording і platform ack policy.- Transport ack: повідомляє platform webhook або socket, що OpenClaw прийняв event envelope. Деякі платформи вимагають цього до dispatch.
- Polling offset ack: просуває cursor, щоб ту саму подію не отримували знову. Це не має просуватися далі за роботу, яку неможливо відновити.
- Inbound record ack: підтверджує, що OpenClaw зберіг достатньо inbound metadata, щоб виконати dedupe і route для повторної доставки.
- User-visible receipt: необов’язкова read/status/typing поведінка; ніколи не є межею надійності.
ReceiveAckPolicy керує лише transport або polling acknowledgement. Його не можна
повторно використовувати для read receipts або status reactions.
Перед авторизацією бота receive має застосувати спільну OpenClaw echo policy,
коли канал може декодувати метадані походження повідомлення:
allowBots.
Ack policy є явною:
getUpdates fetch offset Telegram усе ще контролюється
polling library, тому наступний глибший крок — повністю durable polling
source, якщо нам потрібна platform-level redelivery понад restart
watermark OpenClaw. Webhook platforms можуть потребувати immediate HTTP ack, але їм все одно потрібні
inbound dedupe і durable outbound send intents, бо webhooks можуть redeliver.
Контекст надсилання
Надсилання також базується на контексті:unknown_after_send, а не сліпо повторюватися. Канали
без звірення можуть вибрати повторне відтворення at-least-once лише якщо дублікати видимих
повідомлень є прийнятним, задокументованим компромісом для цього каналу й відношення.
Поточний міст звірення SDK вимагає, щоб адаптер оголосив
reconcileUnknownSend, а потім просить durableFinal.reconcileUnknownSend
класифікувати невідомий запис як sent, not_sent або unresolved; лише not_sent
дозволяє повторне відтворення, а невирішені записи залишаються термінальними або повторюють лише
перевірку звірення.
Політика довговічності має бути явною:
required означає, що ядро має завершуватися із забороною, коли не може записати довговічний намір.
best_effort може продовжити виконання, коли збереження недоступне. disabled зберігає
стару поведінку прямого надсилання. Під час міграції застарілі обгортки й публічні
допоміжні засоби сумісності за замовчуванням використовують disabled; вони не мають виводити required із
того факту, що канал має універсальний вихідний адаптер.
Контексти надсилання також володіють локальними для каналу ефектами після надсилання. Міграція небезпечна,
якщо довговічна доставка обходить локальну поведінку, яка раніше була прив’язана до
шляху прямого надсилання каналу. Приклади включають кеші пригнічення self-echo,
маркери участі в тредах, нативні якорі редагування, рендеринг model-signature
і специфічні для платформи захисти від дублікатів. Ці ефекти мають або перейти в
адаптер надсилання, адаптер рендерингу, або іменований hook контексту надсилання, перш ніж цей
канал зможе ввімкнути довговічну універсальну фінальну доставку.
Допоміжні засоби надсилання мають повертати квитанції аж до свого викликача. Довговічні
обгортки не можуть ковтати id повідомлень або замінювати результат доставки каналу на
undefined; буферизовані диспетчери використовують ці id для якорів тредів, подальших редагувань,
фіналізації попереднього перегляду й пригнічення дублікатів.
Резервні надсилання працюють із пакетами, а не з одиночними payload. Перезаписи silent-reply,
резервний варіант медіа, резервний варіант карток і проєкція чанків можуть створювати більше ніж
одне доставлюване повідомлення, тому контекст надсилання має або доставити весь
спроєктований пакет, або явно задокументувати, чому дійсним є лише один payload.
unknown_after_send, доки адаптер його не звірить.
Живий контекст
Поведінка попереднього перегляду, редагування, прогресу й stream має бути одним opt-in життєвим циклом.- Telegram надсилання плюс редагований попередній перегляд, зі свіжим фінальним повідомленням після застаріння попереднього перегляду.
- Discord надсилання плюс редагований попередній перегляд, скасування на медіа/помилці/явній відповіді.
- Slack нативний stream або чорновий попередній перегляд залежно від форми треду.
- Mattermost фіналізація чорнового допису.
- Matrix фіналізація чорнової події або редагування у разі невідповідності.
- Teams нативний stream прогресу.
- QQ Bot stream або накопичений резервний варіант.
Поверхня адаптера
Публічною ціллю SDK має бути один subpath:origin.decode повертає метадані походження OpenClaw. Адаптер отримання
надає факти платформи, як-от автор bot і форма кімнати; ядро володіє рішенням
про відкидання й порядком, щоб канали не реалізовували текстові фільтри повторно.
Адаптер походження:
MessageOrigin. Канали лише транслюють його до й з нативних
метаданих транспорту. Slack зіставляє це з chat.postMessage({ metadata }) і
вхідним message.metadata; Matrix може зіставляти це з додатковим вмістом події; канали
без нативних метаданих можуть використовувати реєстр квитанцій/вихідних повідомлень, коли це
найкраще доступне наближення.
Можливості:
Скорочення публічного SDK
Нова публічна поверхня має поглинути або зробити застарілими ці концептуальні області:reply-runtimereply-dispatch-runtimereply-referencereply-chunkingreply-payloadinbound-reply-dispatchchannel-reply-pipeline- більшість публічних використань
outbound-runtime - ad hoc допоміжні засоби життєвого циклу draft stream
plugin-sdk/channel-message, щойно він з’явиться.
Зв’язок із channel turn
runtime.channel.turn.* має залишатися під час міграції.
Він має стати адаптером сумісності:
channel.turn.runPrepared також має спочатку залишатися:
channel.turn можна зробити застарілим. Його не слід видаляти, доки не буде
опублікованого шляху міграції SDK і контрактних тестів, які доводять, що старі plugins усе ще працюють
або завершуються з чіткою помилкою версії.
Запобіжники сумісності
Під час міграції універсальна довговічна доставка є opt-in для будь-якого каналу, чий наявний callback доставки має побічні ефекти поза “надіслати цей payload”. Застарілі точки входу за замовчуванням недовговічні:channel.turn.runіdispatchAssembledChannelTurnвикористовують callback доставки каналу, якщо цей канал явно не надає перевірений об’єкт довговічної політики/параметрів.channel.turn.runPreparedзалишається у власності каналу, доки підготовлений диспетчер явно не викличе контекст надсилання.- Публічні допоміжні засоби сумісності, як-от
recordInboundSessionAndDispatchReply,dispatchInboundReplyWithBaseі direct-DM helpers, ніколи не впроваджують універсальну довговічну доставку перед наданим викликачем callbackdeliverабоreply.
durable: undefined означає “не довговічний”. Довговічний
шлях вмикається лише явним значенням політики/параметрів. durable: false може залишатися як написання для сумісності, але реалізація не повинна
вимагати, щоб кожен немігрований канал його додавав.
Поточний код моста має зберігати рішення щодо довговічності явним:
- Стійка фінальна доставка повертає дискримінований статус.
handled_visibleіhandled_no_sendє термінальними;unsupportedіnot_applicableможуть повертатися до доставки, що належить каналу;failedпоширює збій надсилання. - Універсальна стійка фінальна доставка обмежується можливостями адаптера, як-от тиха доставка, збереження цілі відповіді, збереження нативної цитати та хуки надсилання повідомлень. За відсутності паритету слід обирати доставку, що належить каналу, а не універсальне надсилання, яке змінює поведінку, видиму користувачу.
- Стійкі надсилання на основі черги надають посилання на намір доставки. Наявні
поля сеансу
pendingFinalDelivery*можуть переносити ідентифікатор наміру під час переходу; кінцевий стан — сховищеMessageSendIntentзамість замороженого тексту відповіді плюс ad hoc поля контексту.
- Адаптер універсального надсилання виконує ту саму поведінку рендерингу й транспорту, що й старий прямий шлях.
- Локальні побічні ефекти після надсилання зберігаються через контекст надсилання.
- Адаптер повертає квитанції або результати доставки з усіма ідентифікаторами повідомлень платформи.
- Підготовлені шляхи диспетчеризації або викликають новий контекст надсилання, або залишаються задокументованими як такі, що перебувають поза стійкою гарантією.
- Резервна доставка обробляє кожне спроєктоване корисне навантаження, а не лише перше.
- Стійка резервна доставка записує весь масив спроєктованих корисних навантажень як один намір або пакетний план, який можна відтворити повторно.
- Доставка монітора iMessage записує надіслані повідомлення в кеш відлуння після успішного надсилання. Стійкі фінальні надсилання все одно мають заповнювати цей кеш, інакше OpenClaw може повторно приймати власні фінальні відповіді як вхідні повідомлення користувача.
- Tlon додає необов’язковий підпис моделі та записує потоки за участю після групових відповідей. Універсальна стійка доставка не повинна обходити ці ефекти; або перенесіть їх в адаптери рендерингу/надсилання/фіналізації Tlon, або залиште Tlon на шляху, що належить каналу.
- Discord та інші підготовлені диспетчери вже володіють прямою доставкою та поведінкою попереднього перегляду. На них не поширюється стійка гарантія зібраного ходу, доки їхні підготовлені диспетчери явно не маршрутизують фінальні повідомлення через контекст надсилання.
- Тиха резервна доставка Telegram має доставляти повний масив спроєктованих корисних навантажень. Скорочення до одного корисного навантаження може відкинути додаткові резервні корисні навантаження після проєкції.
- LINE, Zalo, Nostr та інші наявні зібрані/допоміжні шляхи можуть мати обробку токенів відповіді, проксіювання медіа, кеші надісланих повідомлень, очищення стану завантаження/статусу або цілі лише для callback. Вони залишаються на доставці, що належить каналу, доки ці семантики не будуть представлені адаптером надсилання й перевірені тестами.
- Допоміжні засоби прямих DM можуть мати callback відповіді, який є єдиною
правильною ціллю транспорту. Універсальний вихідний потік не повинен
вгадувати з
OriginatingToабоToй пропускати цей callback. - Вивід збоїв Gateway OpenClaw має залишатися видимим для людей, але позначені
відлуння кімнати, створені ботом, потрібно відкидати до авторизації
allowBots. Канали не повинні реалізовувати це за допомогою фільтрів префікса видимого тексту, окрім короткого аварійного запобіжника; стійкий контракт — це структуровані метадані походження.
Внутрішнє сховище
Стійка черга повинна зберігати наміри надсилання повідомлень, а не корисні навантаження відповідей.Класи збоїв
Адаптери каналів класифікують транспортні збої в закриті категорії:- Повторювати
transientіrate_limit. - Не повторювати
invalid_payload, якщо немає резервного рендерингу. - Не повторювати
authабоpermission, доки не зміниться конфігурація. - Для
not_foundдозволити live-фіналізації повернутися з редагування до нового надсилання, коли канал оголошує це безпечним. - Для
conflictвикористовуйте правила квитанцій/idempotency, щоб вирішити, чи повідомлення вже існує. - Будь-яка помилка після того, як адаптер міг завершити платформне I/O, але до
фіксації квитанції, стає
unknown_after_send, якщо адаптер не може довести, що платформна операція не відбулася.
Мапінг каналів
| Канал | Цільова міграція |
|---|---|
| Telegram | Отримує політику підтверджень і стійкі фінальні надсилання. Live-адаптер відповідає за надсилання й редагований попередній перегляд, фінальне надсилання застарілого попереднього перегляду, теми, пропуск попереднього перегляду відповіді з цитатою, резервний варіант для медіа та обробку retry-after. |
| Discord | Адаптер надсилання обгортає наявну доставку стійкого payload. Live-адаптер відповідає за редагування чернетки, чернетку прогресу, скасування попереднього перегляду медіа/помилки, збереження цілі відповіді та квитанції ідентифікаторів повідомлень. Перевірте створені ботом відлуння gateway-збоїв у спільних кімнатах; використовуйте вихідний реєстр або інший нативний еквівалент, якщо Discord не може переносити метадані походження у звичайних повідомленнях. |
| Slack | Адаптер надсилання обробляє звичайні дописи в чаті. Live-адаптер обирає нативний потік, коли форма треду це підтримує, інакше використовує попередній перегляд чернетки. Квитанції зберігають часові мітки тредів. Адаптер походження зіставляє gateway-збої OpenClaw із Slack chat.postMessage.metadata і відкидає позначені відлуння бот-кімнат до авторизації allowBots. |
| Адаптер надсилання відповідає за надсилання тексту/медіа зі стійкими фінальними намірами. Адаптер отримання обробляє згадки в групах та ідентичність відправника. Live може лишатися відсутнім, доки WhatsApp не матиме редагованого транспорту. | |
| Matrix | Live-адаптер відповідає за редагування подій-чернеток, фіналізацію, редагування-вилучення, обмеження зашифрованих медіа та резервний варіант у разі невідповідності цілі відповіді. Адаптер отримання відповідає за гідратацію та дедуплікацію зашифрованих подій. Адаптер походження має кодувати походження gateway-збою OpenClaw у вміст події Matrix і відкидати відлуння кімнат налаштованого бота до обробки allowBots. |
| Mattermost | Live-адаптер відповідає за один допис-чернетку, згортання прогресу/інструментів, фіналізацію на місці та резервне свіже надсилання. |
| Microsoft Teams | Live-адаптер відповідає за нативний прогрес і поведінку потокових блоків. Адаптер надсилання відповідає за активності та квитанції вкладень/карток. |
| Feishu | Адаптер рендерингу відповідає за рендеринг тексту/карток/сирого вмісту. Live-адаптер відповідає за потокові картки та пригнічення дубльованого фінального повідомлення. Адаптер надсилання відповідає за коментарі, сесії тем, медіа та пригнічення голосу. |
| QQ Bot | Live-адаптер відповідає за потокове передавання C2C, тайм-аут акумулятора та резервне фінальне надсилання. Адаптер рендерингу відповідає за медіатеги та текст як голос. |
| Signal | Просте отримання плюс адаптер надсилання. Без Live-адаптера, якщо signal-cli не додасть надійну підтримку редагування. |
| iMessage | Просте отримання плюс адаптер надсилання. Надсилання iMessage має зберігати заповнення echo-cache монітора, перш ніж стійкі фінальні повідомлення зможуть обходити доставку через монітор. |
| Google Chat | Просте отримання плюс адаптер надсилання з відношенням треду, зіставленим із просторами та ідентифікаторами тредів. Перевірте поведінку кімнат із allowBots=true для позначених відлунь gateway-збоїв OpenClaw. |
| LINE | Просте отримання плюс адаптер надсилання з обмеженнями reply-token, змодельованими як можливість цілі/відношення. |
| Nextcloud Talk | Міст отримання SDK плюс адаптер надсилання. |
| IRC | Просте отримання плюс адаптер надсилання, без стійких квитанцій редагування. |
| Nostr | Адаптер отримання плюс надсилання для зашифрованих DM; квитанції є ідентифікаторами подій. |
| QA Channel | Адаптер контрактних тестів для поведінки отримання, надсилання, Live, повтору та відновлення. |
| Synology Chat | Просте отримання плюс адаптер надсилання. |
| Tlon | Адаптер надсилання має зберігати рендеринг підпису моделі та відстеження тредів за участю, перш ніж буде ввімкнено загальну стійку фінальну доставку. |
| Twitch | Просте отримання плюс адаптер надсилання з класифікацією обмежень швидкості. |
| Zalo | Просте отримання плюс адаптер надсилання. |
| Zalo Personal | Просте отримання плюс адаптер надсилання. |
План міграції
Фаза 1: Внутрішній домен повідомлень
- Додайте типи
src/channels/message/*для повідомлень, цілей, відношень, походжень, квитанцій, можливостей, стійких намірів, контексту отримання, контексту надсилання, live-контексту та класів збоїв. - Додайте
origin?: MessageOriginдо типу payload міграційного мосту, який використовується поточною доставкою відповідей, а потім перенесіть це поле доChannelMessageі типів відрендерених повідомлень, коли рефакторинг замінить payload відповідей. - Тримайте це внутрішнім, доки адаптери й тести не доведуть форму.
- Додайте чисті модульні тести для переходів стану та серіалізації.
Фаза 2: Ядро стійкого надсилання
- Перенесіть наявну вихідну чергу зі стійкості reply-payload до стійких намірів надсилання повідомлень.
- Дозвольте стійкому наміру надсилання переносити масив спроєктованих payload або план пакета, а не лише один reply payload.
- Збережіть поточну поведінку відновлення черги через конверсію сумісності.
- Зробіть так, щоб
deliverOutboundPayloadsвикликавmessages.send. - Зробіть стійкість фінального надсилання типовою і відмовляйте закрито, коли стійкий намір не можна записати в новому життєвому циклі повідомлення, після того як адаптер оголосить безпечність повторного відтворення. Наявні шляхи сумісності channel-turn і SDK залишаються direct-send за замовчуванням протягом цієї фази.
- Послідовно записуйте квитанції.
- Повертайте квитанції та результати доставки початковому викликачеві диспетчера замість трактування стійкого надсилання як термінального побічного ефекту.
- Зберігайте походження повідомлення через стійкі наміри надсилання, щоб відновлення, повторне відтворення та фрагментовані надсилання зберігали операційне походження OpenClaw.
Фаза 3: Міст обороту каналу
- Повторно реалізуйте
channel.turn.runіdispatchAssembledChannelTurnповерхmessages.receiveіmessages.send. - Збережіть поточні типи фактів стабільними.
- Збережіть за замовчуванням застарілу поведінку. Канал assembled-turn стає стійким лише тоді, коли його адаптер явно погоджується з replay-safe політикою стійкості.
- Збережіть
durable: falseяк запасний шлях сумісності для шляхів, які фіналізують нативні редагування і ще не можуть безпечно відтворюватися повторно, але не покладайтеся на маркериfalse, щоб захищати немігрові канали. - Умикайте типову стійкість assembled-turn лише в новому життєвому циклі повідомлень, після того як зіставлення каналу доведе, що загальний шлях надсилання зберігає стару семантику доставки каналу.
Фаза 4: Міст підготовленого диспетчера
- Замініть
deliverDurableInboundReplyPayloadмостом через контекст надсилання. - Залиште старий допоміжний засіб як обгортку.
- Спершу перенесіть Telegram, WhatsApp, Slack, Signal, iMessage і Discord, тому що вони вже мають роботу зі стійким фіналом або простіші шляхи надсилання.
- Вважайте кожен підготовлений диспетчер непокритим, доки він явно не підключиться до контексту надсилання. Документація та записи журналу змін мають казати “зібрані оберти каналу” або називати перенесені шляхи каналів, а не заявляти про всі автоматичні фінальні відповіді.
- Збережіть поведінку
recordInboundSessionAndDispatchReply, допоміжних засобів direct-DM та подібних публічних допоміжних засобів сумісності. Пізніше вони можуть надати явне підключення до контексту надсилання, але не повинні автоматично намагатися виконувати загальну стійку доставку перед callback доставки, яким володіє викликач.
Фаза 5: Уніфікований Життєвий Цикл Live
- Побудуйте
messages.liveз двома адаптерами доказу:- Telegram для надсилання плюс редагування плюс надсилання застарілого фіналу.
- Matrix для фіналізації чернетки плюс резервне редагування.
- Потім перенесіть Discord, Slack, Mattermost, Teams, QQ Bot і Feishu.
- Видаляйте дубльований код фіналізації попереднього перегляду лише після того, як кожен канал матиме тести паритету.
Фаза 6: Публічний SDK
- Додайте
openclaw/plugin-sdk/channel-message. - Задокументуйте його як бажаний API Plugin каналу.
- Оновіть експорти пакета, інвентар entrypoint, згенеровані базові лінії API та документацію SDK Plugin.
- Включіть
MessageOrigin, хуки кодування/декодування origin і спільний предикатshouldDropOpenClawEchoдо поверхні SDK channel-message. - Збережіть обгортки сумісності для старих підшляхів.
- Позначте допоміжні засоби SDK з назвами reply як застарілі в документації після перенесення вбудованих plugins.
Фаза 7: Усі Відправники
Перенесіть усіх вихідних продуцентів, що не є відповідями, наmessages.send:
- сповіщення cron і Heartbeat
- завершення завдань
- результати hook
- запити на схвалення та результати схвалення
- надсилання через інструмент повідомлень
- оголошення про завершення subagent
- явні надсилання CLI або Control UI
- шляхи автоматизації/трансляції
Фаза 8: Виведення Turn з ужитку
- Залиште
channel.turnяк обгортку принаймні на одне вікно сумісності. - Опублікуйте нотатки міграції.
- Запустіть тести сумісності SDK Plugin зі старими імпортами.
- Видаляйте або приховуйте старі внутрішні допоміжні засоби лише після того, як жоден вбудований plugin їх більше не потребуватиме, а сторонні контракти матимуть стабільну заміну.
План тестування
Модульні тести:- Серіалізація та відновлення стійкого наміру надсилання.
- Повторне використання ключа ідемпотентності та придушення дублікатів.
- Commit квитанції та пропуск replay.
- Відновлення
unknown_after_send, яке узгоджує перед replay, коли адаптер підтримує узгодження. - Політика класифікації відмов.
- Послідовність політики ack приймання.
- Мапінг зв’язків для надсилань reply, followup, system і broadcast.
- Фабрика origin для відмов Gateway та предикат
shouldDropOpenClawEcho. - Збереження origin через нормалізацію payload, chunking, серіалізацію стійкої черги та відновлення.
- Простий адаптер
channel.turn.runусе ще записує та надсилає. - Доставка застарілого зібраного оберту не стає стійкою, якщо канал явно не підключився.
- Міст
channel.turn.runPreparedусе ще записує та фіналізує. - Публічні допоміжні засоби сумісності типово викликають callback доставки, яким володіє викликач, і не виконують загальне надсилання перед цими callback.
- Стійка резервна доставка відтворює весь спроєктований масив payload після перезапуску і не може залишити пізніші payload незаписаними після раннього збою.
- Стійка доставка зібраного оберту повертає ідентифікатори повідомлень платформи до буферизованого диспетчера.
- Користувацькі hook доставки все ще повертають ідентифікатори повідомлень платформи, коли стійку доставку вимкнено або вона недоступна.
- Фінальна відповідь переживає перезапуск між завершенням асистента та надсиланням на платформу.
- Чернетка попереднього перегляду фіналізується на місці, коли це дозволено.
- Чернетка попереднього перегляду скасовується або редагується, коли медіа/помилка/невідповідність цілі відповіді потребує звичайної доставки.
- Потокове передавання блоків і потокове передавання попереднього перегляду не доставляють той самий текст обидва.
- Медіа, передане потоково раніше, не дублюється у фінальній доставці.
- Відповідь у темі Telegram з ack polling, затриманим до безпечної завершеної watermark контексту приймання.
- Відновлення polling Telegram для прийнятих, але не доставлених оновлень, покрите збереженою моделлю safe-completed offset.
- Застарілий попередній перегляд Telegram надсилає свіжий фінал і прибирає попередній перегляд.
- Тихий резерв Telegram надсилає кожен спроєктований резервний payload.
- Стійкість тихого резерву Telegram атомарно записує повний спроєктований резервний масив, а не один стійкий намір з одиночним payload на кожну ітерацію циклу.
- Скасування попереднього перегляду Discord у разі медіа/помилки/явної відповіді.
- Фінали підготовленого диспетчера Discord маршрутизуються через контекст надсилання до того, як документація або журнал змін заявлять про стійкість фінальних відповідей Discord.
- Стійкі фінальні надсилання iMessage заповнюють кеш echo надісланих повідомлень монітора.
- Застарілі шляхи доставки LINE, Zalo і Nostr не обходяться загальним стійким надсиланням, доки не існують тести паритету їхнього адаптера.
- Доставка callback Direct-DM/Nostr лишається авторитетною, якщо її явно не перенесено на повну ціль повідомлення та replay-безпечний адаптер надсилання.
- Позначені Slack повідомлення про відмову Gateway OpenClaw лишаються видимими назовні, позначені
echo bot-room відкидаються перед
allowBots, а непозначені повідомлення bot з тим самим видимим текстом усе ще проходять звичайну авторизацію bot. - Резервний варіант нативного потоку Slack до чернетки попереднього перегляду в DMs верхнього рівня.
- Фіналізація попереднього перегляду Matrix і резервне редагування.
- Позначені Matrix echo кімнати про gateway-failure OpenClaw від налаштованих облікових записів bot
відкидаються перед обробкою
allowBots. - Аудити cascade gateway-failure у спільних кімнатах Discord і Google Chat покривають
режими
allowBotsперед заявами про загальний захист там. - Фіналізація чернетки Mattermost і резервне надсилання свіжого повідомлення.
- Фіналізація нативного прогресу Teams.
- Придушення дубльованого фіналу Feishu.
- Резерв accumulator timeout QQ Bot.
- Стійкі фінальні надсилання Tlon зберігають рендеринг model-signature і відстеження потоків, у яких була участь.
- Прості стійкі фінальні надсилання WhatsApp, Signal, iMessage, Google Chat, LINE, IRC, Nostr, Nextcloud Talk, Synology Chat, Tlon, Twitch, Zalo і Zalo Personal.
- Цільові файли Vitest під час розробки.
pnpm check:changedу Testbox для всієї зміненої поверхні.- Ширший
pnpm checkу Testbox перед landing повного рефакторингу або після змін публічного SDK/export. - Live або qa-channel smoke принаймні для одного каналу з можливістю редагування та одного простого каналу лише з надсиланням перед видаленням обгорток сумісності.
Відкриті питання
- Чи має Telegram зрештою замінити джерело runner grammY на повністю стійке джерело polling, яке може контролювати повторну доставку на рівні платформи, а не лише збережену watermark перезапуску OpenClaw.
- Чи слід зберігати стан стійкого live preview у тому самому записі черги, що й фінальний намір надсилання, або в сусідньому сховищі live-state.
- Як довго обгортки сумісності лишаються задокументованими після випуску
plugin-sdk/channel-message. - Чи повинні сторонні plugins реалізовувати адаптери приймання напряму, чи лише
надавати hooks normalize/send/live через
defineChannelMessageAdapter. - Які поля квитанцій безпечно відкривати в публічному SDK, а які належать до внутрішнього runtime state.
- Чи слід моделювати побічні ефекти, як-от кеші self-echo і маркери participated-thread, як hook контексту надсилання, кроки finalize, якими володіє адаптер, або підписників на квитанції.
- Які канали мають нативні metadata origin, які потребують збережених вихідних реєстрів, а які не можуть забезпечити надійне придушення echo між bot.
Критерії прийняття
- Кожен вбудований канал повідомлень надсилає фінальний видимий вивід через
messages.send. - Кожен вхідний канал повідомлень входить через
messages.receiveабо задокументовану обгортку сумісності. - Кожен канал попереднього перегляду/редагування/потоку використовує
messages.liveдля стану чернетки та фіналізації. channel.turnє лише обгорткою.- Допоміжні засоби SDK з назвами reply є експортами сумісності, а не рекомендованим шляхом.
- Стійке відновлення може відтворювати очікувані фінальні надсилання після перезапуску без втрати фінальної відповіді або дублювання вже commit надсилань; надсилання, чий результат на платформі невідомий, узгоджуються перед replay або документуються як at-least-once для цього адаптера.
- Стійкі фінальні надсилання fail closed, коли стійкий намір неможливо записати, якщо тільки викликач явно не вибрав задокументований нестійкий режим.
- Застарілі channel-turn і допоміжні засоби сумісності SDK типово використовують пряму доставку, якою володіє канал; загальне стійке надсилання є лише явним opt-in.
- Квитанції зберігають усі ідентифікатори повідомлень платформи для багаточастинних доставок і первинний ідентифікатор для зручності threading/edit.
- Стійкі обгортки зберігають локальні для каналу побічні ефекти перед заміною прямих callback доставки.
- Підготовлені диспетчери не вважаються стійкими, доки їхній фінальний шлях доставки явно не використовує контекст надсилання.
- Резервна доставка обробляє кожен спроєктований payload.
- Стійка резервна доставка записує кожен спроєктований payload в один replay-able намір або пакетний план.
- Вивід про відмову Gateway, створений OpenClaw, видимий для людей, але позначені echo кімнати, автором яких є bot, відкидаються перед авторизацією bot на каналах, що оголошують підтримку контракту origin.
- Документація пояснює надсилання, приймання, live, state, квитанції, зв’язки, політику відмов, міграцію та тестове покриття.