---
read_when:
    - Ви створюєте або рефакторите шлях надсилання в Plugin каналу обміну повідомленнями
    - Вам потрібні надійна доставка остаточної відповіді, підтвердження отримання, завершення попереднього перегляду в реальному часі або політика підтвердження приймання
    - Ви переходите з допоміжних засобів надсилання відповідей channel-message, channel-message-runtime або застарілих засобів диспетчеризації відповідей
summary: 'API життєвого циклу вихідних повідомлень для плагінів каналів: адаптери, підтвердження, надійне надсилання, попередній перегляд у реальному часі та допоміжні засоби конвеєра відповідей'
title: API вихідних повідомлень каналу
x-i18n:
    generated_at: "2026-07-12T13:32:49Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    provider: openai
    source_hash: 6ab3c38a0c2ae7d46f318604328b5ffdd6f375005150f09698b299cbd06e2f22
    source_path: plugins/sdk-channel-outbound.md
    workflow: 16
---

Плагіни каналів надають поведінку вихідних повідомлень через
`openclaw/plugin-sdk/channel-outbound`. Використовуйте
`openclaw/plugin-sdk/channel-inbound` для оркестрації
отримання/контексту/диспетчеризації.

Ядро відповідає за постановку в чергу, надійність, загальну політику повторних спроб, хуки, квитанції та
спільний інструмент `message`. Плагін відповідає за нативні виклики надсилання/редагування/видалення,
нормалізацію цілі, гілки обговорень платформи, вибрані цитати, прапорці
сповіщень, стан облікового запису та специфічні для платформи побічні ефекти.

## Адаптер

Більшість плагінів визначають один адаптер `message`:

```ts
import {
  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,
        }),
      };
    },
  },
});
```

Оголошуйте лише ті можливості, які нативний транспорт справді зберігає. Охоплюйте
кожну оголошену можливість надсилання, квитанції, попереднього перегляду в реальному часі та підтвердження отримання
контрактними допоміжними функціями, експортованими з цього підшляху.

## Очищення звичайного тексту

Використовуйте `sanitizeForPlainText(...)`, коли вихідному адаптеру потрібно перетворити
підтримувані HTML-теги форматування на полегшену текстову розмітку. Типово зберігаються
наявні маркери жирного та закресленого тексту в стилі чату. Передавайте
`{ style: "markdown" }` лише тоді, коли канал повторно аналізує результат як Markdown:

```ts
import { sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";

const chatText = sanitizeForPlainText(text);
const markdownText = sanitizeForPlainText(text, { style: "markdown" });
```

Стиль Markdown використовує `**bold**` і `~~strikethrough~~`; курсив і вбудований
код зберігають маркери `_italic_` і зворотні апострофи в обох стилях. Вибирайте стиль на
межі каналу замість переписування тексту маркерів після очищення.

## Свідчення доставки

`MessageReceipt` фіксує результат, повернений адаптером каналу. Конкретні
ідентифікатори повідомлень платформи свідчать, що шлях надсилання платформи прийняв
повідомлення; вони не доводять, що пристрій одержувача відобразив або прочитав його.
Квитанції без ідентифікаторів повідомлень платформи є лише локальними метаданими квитанцій.
Канали з квитанціями про прочитання або станом доставки на пристрій мають відстежувати ці факти
через окремий специфічний для каналу шлях.

Якщо адаптер каналу може довести, що повторна спроба після помилки не може дублювати
видиме одержувачу надсилання й не було розпочато жодного виклику, здатного виконати фіналізацію, викиньте
`new PlatformMessageNotDispatchedError("...", { cause: error })` з
`openclaw/plugin-sdk/error-runtime`. Тоді ядро може очистити застарілі свідчення
спроби надсилання та безпечно повторити поставлений у чергу намір. Лише адаптер, якому належить
остаточна межа диспетчеризації, може робити це твердження. Ніколи не використовуйте цей маркер після
початку виклику фіналізації/надсилання або якщо він повертає неоднозначний результат; хибне маркування може
дублювати повідомлення.

## Наявні вихідні адаптери

Якщо канал уже має сумісний адаптер `outbound`, створюйте на його основі
адаптер повідомлень замість дублювання коду надсилання:

```ts
import { createChannelMessageAdapterFromOutbound } from "openclaw/plugin-sdk/channel-outbound";

export const messageAdapter = createChannelMessageAdapterFromOutbound({
  id: "demo",
  outbound,
  durableFinal: {
    capabilities: {
      text: true,
      media: true,
    },
  },
});
```

## Надійні надсилання

Допоміжні функції надсилання середовища виконання також доступні в `channel-outbound`:

- `sendDurableMessageBatch(...)`
- `withDurableMessageSendContext(...)`
- `deliverInboundReplyWithMessageSendContext(...)`
- допоміжні функції потокового передавання чернеток/прогресу, як-от `resolveChannelDraftStreamingChunking(...)`

`sendDurableMessageBatch(...)` повертає один явний результат:

| Результат        | Значення                                                                                |
| ---------------- | --------------------------------------------------------------------------------------- |
| `sent`           | шлях надсилання платформи прийняв принаймні одне видиме повідомлення платформи           |
| `suppressed`     | жодне повідомлення платформи не слід вважати відсутнім                                  |
| `partial_failed` | принаймні одне повідомлення платформи було прийнято до помилки наступного корисного навантаження або побічного ефекту |
| `failed`         | квитанцію платформи не створено                                                         |

Використовуйте `payloadOutcomes`, коли пакет поєднує надіслані, пригнічені та невдалі
корисні навантаження. Не робіть висновок про скасування хуком на основі порожнього застарілого
результату прямої доставки.

## Допуск відкладеної доставки

Використовуйте `message.durableFinal.admitDeferredDelivery(...)`, коли визначений обліковий запис
не може безпечно приймати керовану ядром вихідну або відкладену доставку. Ядро викликає
цей хук синхронно перед вихідною роботою в реальному часі, включно зі шляхами, що пропускають
збереження в черзі, і повторно перед відтворенням відновленого наміру. Контекст
містить `cfg`, `channel`, `to`, `accountId` і `phase` зі значенням `live` або
`recovery`.

Поверніть `{ status: "allowed" }`, щоб продовжити. Поверніть
`{ status: "permanent_rejection", reason }`, коли доставку не можна
зберігати, надсилати напряму або відтворювати. Відхилення в реальному часі спричиняє помилку до створення
черги, хуків повідомлень або роботи з платформою. Відхилення під час відновлення позначає
запис у черзі як невдалий і пропускає узгодження та відтворення. Відсутність хука
означає дозвіл.

Хук є синхронним рішенням про допуск, а не шляхом надсилання. Читайте лише
вже завантажену конфігурацію або стан середовища виконання; не виконуйте мережеве, файлове чи
інше асинхронне введення-виведення. Контрактні тести мають перевіряти обидві фази та обидва
варіанти результату через `ChannelMessageDurableFinalAdapter` з
`openclaw/plugin-sdk/channel-outbound`.

## Диспетчеризація сумісності

Формуйте диспетчеризацію вхідної відповіді через `dispatchChannelInboundReply(...)`
з `channel-inbound`. Зберігайте доставку платформи в адаптері доставки; використовуйте
`channel-outbound` для адаптерів повідомлень, надійних надсилань, квитанцій, попереднього
перегляду в реальному часі та параметрів конвеєра відповідей.
