Channel outbound API
기준일: 2026-07-26
공식 기준: Channel outbound API
Channel outbound API 문서는 OpenClaw 공식 문서(plugins/sdk-channel-outbound)를 한국어로 정리한 가이드입니다. Outbound message lifecycle API for channel plugins: adapters, receipts, durable sends, live preview, and reply pipeline helpers 명령·설정 키·코드 예시는 공식 문서를 그대로 보존하며, 해석과 절차 안내는 한국어로 제공합니다. 최종 동작은 설치된 CLI 버전과 공식 원문을 확인하세요.
핵심 요약
Outbound message lifecycle API for channel plugins: adapters, receipts, durable sends, live preview, and reply pipeline helpers
한국어 가이드 범위: plugins/sdk-channel-outbound 경로의 설정·명령·제약·예시를 학습용으로 재구성합니다.
문서 구성
공식 문서의 주요 섹션은 다음과 같습니다.
- Durable ingress monitors
- Adapter
- Outbound echo suppression
- Plain-text sanitization
- Delivery Evidence
- Existing outbound adapters
- Durable sends
- Deferred delivery admission
- Compatibility dispatch
상세 내용
본문
Channel plugins expose outbound message behavior from openclaw/plugin-sdk/channel-outbound. Use openclaw/plugin-sdk/channel-inbound for receive/context/dispatch orchestration.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Durable ingress monitors
Use createChannelIngressMonitor(...) when a channel must persist accepted transport events before dispatch. It composes a channel ingress queue and drain with the shared admission, polling, pruning, delivery, and shutdown lifecycle. Use the lower-level createChannelIngressDrain(...) only when the transport owns a materially different admission or pump contract.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
| Option | Contract |
|---|---|
queue |
A ChannelIngressQueue, or a lazy factory that opens the account-scoped queue. |
inspect(raw, context) |
Returns the stable eventId and serialized laneKey, or null for an ignored event. Claim-time facts must match the persisted id and lane. |
payload |
Supplies the payload version plus body serialization/deserialization. Use storage: "raw-event" for the standard { version, rawEvent } string envelope, or provide custom encode/decode callbacks for an existing channel-specific shape. createClaimError classifies invalid versions or changed identity. |
deliver(raw, lifecycle, claim) |
Dispatches one decoded event and receives the complete adoption lifecycle. It may return completed, deferred, failed-retryable, or nothing. |
pollIntervalMs |
Schedules recovery/drain polls while the monitor is running. |
retention |
Supplies the prune cadence and completed/failed TTL and entry caps. |
Adapter
Most plugins define one message adapter:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
defineChannelMessageAdapter,
createMessageReceiptFromOutboundResults,
} from "openclaw/plugin-sdk/channel-outbound";
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,
}),
};
},
},
});
Outbound echo suppression
When a platform may redeliver the plugin's own outbound message as inbound, call recordOutboundMessageIdentity(...) with the channel, account, conversation, and a stable platform message or source identity. The shared inbound turn path drops matching identities for a bounded 30-second window before session recording or agent dispatch; a source identity may be reserved before send or refreshed when a channel route is removed to close delivery races. isRecentOutboundMessageIdentity(...) exposes the same query for channel diagnostics and tests. Do not maintain a parallel channel-local TTL cache for the same stable identity.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Plain-text sanitization
Use sanitizeForPlainText(...) when an outbound adapter needs to convert the supported HTML formatting tags into lightweight text markup. The default keeps the existing chat-style bold and strikethrough markers. Pass { style: "markdown" } only when the channel reparses the result as Markdown:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
const chatText = sanitizeForPlainText(text);
const markdownText = sanitizeForPlainText(text, { style: "markdown" });
Delivery Evidence
A MessageReceipt records the result returned by a channel adapter. Concrete platform message identifiers show that the platform send path accepted the message; they do not prove that a recipient's device displayed or read it. Receipts without platform message identifiers are local receipt metadata only. Channels with read receipts or device-delivery state should track those facts through a separate channel-specific path.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Existing outbound adapters
If the channel already has a compatible outbound adapter, derive the message adapter instead of duplicating send code:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
id: "demo",
outbound,
durableFinal: {
capabilities: {
text: true,
media: true,
},
},
});
Durable sends
Runtime send helpers also live on channel-outbound:
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
주요 항목:
sendDurableMessageBatch(...)withDurableMessageSendContext(...)deliverInboundReplyWithMessageSendContext(...)- draft streaming/progress helpers such as
resolveChannelDraftStreamingChunking(...)
| Outcome | Meaning |
|---|---|
sent |
at least one visible platform message was accepted by the platform send path |
suppressed |
no platform message should be treated as missing |
partial_failed |
at least one platform message was accepted before a later payload or side effect failed |
failed |
no platform receipt was produced |
Deferred delivery admission
Use message.durableFinal.admitDeferredDelivery(...) when a resolved account cannot safely accept core-managed outbound or deferred delivery. Core calls this hook synchronously before live outbound work, including paths that skip queue persistence, and again before replaying a recovered intent. The context includes cfg, channel, to, accountId, and a phase of live or recovery.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
Compatibility dispatch
Assemble inbound reply dispatch through dispatchChannelInboundReply(...) from channel-inbound. Keep platform delivery in the delivery adapter; use channel-outbound for message adapters, durable sends, receipts, live preview, and reply pipeline options.
위 내용은 공식 문서의 해당 섹션 요지입니다. 세부 플래그·기본값은 원문과
--help를 확인하세요.
실습 체크리스트
- 공식 문서와 로컬 버전을 대조합니다:
https://docs.openclaw.ai/plugins/sdk-channel-outbound - 관련 CLI는
openclaw --help및 하위 명령--help로 옵션을 확인합니다. - 설정 변경 시
openclaw config/openclaw doctor로 유효성을 검사합니다. - Gateway·채널·플러그인 변경 후에는 필요 시 Gateway를 재시작합니다.
자주 쓰는 명령·설정 예시
defineChannelMessageAdapter,
createMessageReceiptFromOutboundResults,
} from "openclaw/plugin-sdk/channel-outbound";
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,
}),
};
},
},
});
const chatText = sanitizeForPlainText(text);
const markdownText = sanitizeForPlainText(text, { style: "markdown" });
id: "demo",
outbound,
durableFinal: {
capabilities: {
text: true,
media: true,
},
},
});
관련 링크
이 가이드는 공식 문서를 한국어 학습용으로 재구성한 것입니다. 옵션 기본값·플래그 이름은 설치 버전에 따라 달라질 수 있습니다.