- 텍스트 섹션
- 작은 컨텍스트/푸터 텍스트
- 구분선
- 버튼
- 선택 메뉴
- 카드 제목 및 tone
components, Slack
blocks, Telegram buttons, Teams card, Feishu card 같은 새로운 provider 네이티브 필드를 공용
message tool에 추가하지 마세요. 이것들은 채널 Plugin이 소유하는 렌더러 출력입니다.
계약
Plugin 작성자는 다음에서 공개 계약을 import합니다.value는 채널이 클릭 가능한 제어를 지원할 때 채널의 기존 상호작용 경로를 통해 다시 라우팅되는 애플리케이션 작업 값입니다.url은 링크 버튼입니다.value없이 존재할 수 있습니다.label은 필수이며 텍스트 대체에서도 사용됩니다.style은 권고 사항입니다. 렌더러는 지원되지 않는 스타일을 전송 실패가 아니라 안전한 기본값으로 매핑해야 합니다.
options[].value는 선택된 애플리케이션 값입니다.placeholder는 권고 사항이며 네이티브 select 지원이 없는 채널에서는 무시될 수 있습니다.- 채널이 select를 지원하지 않으면 대체 텍스트에 레이블 목록이 표시됩니다.
Producer 예시
간단한 카드:렌더러 계약
채널 Plugins는 아웃바운드 어댑터에서 렌더 지원을 선언합니다.코어 렌더 흐름
ReplyPayload 또는 message action에 presentation이 포함되면 core는:
- presentation payload를 정규화합니다.
- 대상 채널의 아웃바운드 어댑터를 확인합니다.
presentationCapabilities를 읽습니다.- 어댑터가 payload를 렌더링할 수 있으면
renderPresentation을 호출합니다. - 어댑터가 없거나 렌더링할 수 없으면 보수적인 텍스트로 대체합니다.
- 결과 payload를 일반 채널 전달 경로로 전송합니다.
- 첫 번째 성공적인
전송 메시지 후
delivery.pin같은 전달 메타데이터를 적용합니다.
저하 규칙
Presentation은 제한된 채널에서도 안전하게 전송될 수 있어야 합니다. 대체 텍스트에는 다음이 포함됩니다.- 첫 줄로서의
title - 일반 문단으로서의
text블록 - 간결한 컨텍스트 줄로서의
context블록 - 시각적 구분자로서의
divider블록 - 링크 버튼의 URL을 포함한 버튼 레이블
- 선택 옵션 레이블
- 인라인 버튼이 비활성화된 Telegram은 텍스트 fallback을 보냅니다.
- select를 지원하지 않는 채널은 select 옵션을 텍스트로 나열합니다.
- URL 전용 버튼은 네이티브 링크 버튼 또는 fallback URL 줄이 됩니다.
- 선택적 pin 실패는 전달된 메시지를 실패시키지 않습니다.
delivery.pin.required: true입니다. pin이
필수로 요청되었는데 채널이 전송된 메시지를 pin할 수 없으면 전달은 실패로 보고됩니다.
Provider 매핑
현재 번들 렌더러:| 채널 | 네이티브 렌더 대상 | 참고 |
|---|---|---|
| Discord | Components 및 component containers | 기존 provider 네이티브 payload producer를 위해 레거시 channelData.discord.components를 유지하지만, 새 공용 전송은 presentation을 사용해야 합니다. |
| Slack | Block Kit | 기존 provider 네이티브 payload producer를 위해 레거시 channelData.slack.blocks를 유지하지만, 새 공용 전송은 presentation을 사용해야 합니다. |
| Telegram | 텍스트 + 인라인 키보드 | 버튼/select는 대상 표면에 인라인 버튼 capability가 필요하며, 그렇지 않으면 텍스트 fallback이 사용됩니다. |
| Mattermost | 텍스트 + interactive props | 다른 블록은 텍스트로 저하됩니다. |
| Microsoft Teams | Adaptive Cards | 둘 다 제공되면 일반 message 텍스트가 카드와 함께 포함됩니다. |
| Feishu | Interactive cards | 카드 헤더는 title을 사용할 수 있으며, 본문은 그 제목을 중복하지 않습니다. |
| Plain channels | 텍스트 fallback | 렌더러가 없는 채널도 읽을 수 있는 출력을 받습니다. |
Presentation vs InteractiveReply
InteractiveReply는 승인 및 상호작용
헬퍼가 사용하는 이전 내부 하위 집합입니다. 지원 항목:
- text
- buttons
- selects
MessagePresentation이 정식 공용 전송 계약입니다. 추가 항목:
- title
- tone
- context
- divider
- URL 전용 버튼
ReplyPayload.delivery를 통한 일반 전달 메타데이터
openclaw/plugin-sdk/interactive-runtime의 헬퍼를 사용하세요.
MessagePresentation을 직접 받아들이거나 생성해야 합니다.
Delivery Pin
Pinning은 프레젠테이션이 아니라 전달 동작입니다.channelData.telegram.pin 같은
provider 네이티브 필드 대신 delivery.pin을 사용하세요.
의미 체계:
pin: true는 첫 번째로 성공적으로 전달된 메시지를 pin합니다.pin.notify의 기본값은false입니다.pin.required의 기본값은false입니다.- 선택적 pin 실패는 저하되며 전송된 메시지는 그대로 유지됩니다.
- 필수 pin 실패는 전달을 실패시킵니다.
- Chunked 메시지는 마지막 chunk가 아니라 첫 번째 전달된 chunk를 pin합니다.
pin, unpin, pins message action은 provider가 해당 작업을 지원하는 기존
메시지에 대해 여전히 존재합니다.
Plugin 작성자 체크리스트
- 채널이 시맨틱 프레젠테이션을 렌더링하거나 안전하게 저하시킬 수 있으면
describeMessageTool(...)에서presentation을 선언하세요. - 런타임 아웃바운드 어댑터에
presentationCapabilities를 추가하세요. renderPresentation은 제어 평면 Plugin 설정 코드가 아니라 런타임 코드에 구현하세요.- 네이티브 UI 라이브러리는 뜨거운 setup/catalog 경로 밖에 두세요.
- 플랫폼 제한은 렌더러와 테스트에 보존하세요.
- 지원되지 않는 버튼, select, URL 버튼, 제목/텍스트
중복, 혼합된
message+presentation전송에 대한 fallback 테스트를 추가하세요. - provider가 전송된 메시지 ID를 pin할 수 있을 때만
deliveryCapabilities.pin과pinDeliveredMessage를 통해 전달 pin 지원을 추가하세요. - 공용 message action 스키마를 통해 새로운 provider 네이티브 카드/블록/컴포넌트/버튼 필드를 노출하지 마세요.