- seções de texto
- texto pequeno de contexto/rodapé
- divisores
- botões
- menus select
- título e tom do card
components do Discord, blocks do Slack,
buttons do Telegram, card do Teams ou card do Feishu, à ferramenta de
mensagem compartilhada. Essas são saídas de renderizador controladas pelo Plugin de canal.
Contrato
Autores de Plugin importam o contrato público de:valueé um valor de ação da aplicação roteado de volta pelo caminho de interação existente do canal quando o canal oferece suporte a controles clicáveis.urlé um botão de link. Ele pode existir semvalue.labelé obrigatório e também é usado no fallback em texto.styleé consultivo. Os renderizadores devem mapear estilos não compatíveis para um padrão seguro, não falhar no envio.
options[].valueé o valor de aplicação selecionado.placeholderé consultivo e pode ser ignorado por canais sem suporte nativo a select.- Se um canal não oferecer suporte a selects, o texto de fallback lista os rótulos.
Exemplos de produtor
Card simples:Contrato do renderizador
Plugins de canal declaram suporte de renderização em seu adaptador de saída:Fluxo de renderização do core
Quando umReplyPayload ou ação de mensagem inclui presentation, o core:
- Normaliza o payload de apresentação.
- Resolve o adaptador de saída do canal de destino.
- Lê
presentationCapabilities. - Chama
renderPresentationquando o adaptador pode renderizar o payload. - Recorre a texto conservador quando o adaptador está ausente ou não consegue renderizar.
- Envia o payload resultante pelo caminho normal de entrega do canal.
- Aplica metadados de entrega, como
delivery.pin, após a primeira mensagem enviada com sucesso.
Regras de degradação
A apresentação deve ser segura para envio em canais limitados. O texto de fallback inclui:titlecomo primeira linha- blocos
textcomo parágrafos normais - blocos
contextcomo linhas compactas de contexto - blocos
dividercomo separador visual - rótulos de botão, incluindo URLs para botões de link
- rótulos de opção de select
- Telegram com botões inline desativados envia fallback em texto.
- Um canal sem suporte a select lista as opções de select como texto.
- Um botão somente com URL torna-se ou um botão de link nativo ou uma linha de URL em fallback.
- Falhas opcionais de fixação não fazem a mensagem entregue falhar.
delivery.pin.required: true; se a fixação for solicitada como
obrigatória e o canal não puder fixar a mensagem enviada, a entrega relata falha.
Mapeamento de provedor
Renderizadores empacotados atuais:| Canal | Alvo de renderização nativo | Observações |
|---|---|---|
| Discord | Components e contêineres de componente | Preserva channelData.discord.components legado para produtores existentes de payload nativo de provedor, mas novos envios compartilhados devem usar presentation. |
| Slack | Block Kit | Preserva channelData.slack.blocks legado para produtores existentes de payload nativo de provedor, mas novos envios compartilhados devem usar presentation. |
| Telegram | Texto mais teclados inline | Botões/selects exigem capacidade de botão inline para a superfície de destino; caso contrário, é usado fallback em texto. |
| Mattermost | Texto mais props interativas | Outros blocos sofrem degradação para texto. |
| Microsoft Teams | Adaptive Cards | O texto simples message é incluído com o card quando ambos são fornecidos. |
| Feishu | Cards interativos | O cabeçalho do card pode usar title; o corpo evita duplicar esse título. |
| Canais simples | Fallback em texto | Canais sem renderizador ainda recebem saída legível. |
Presentation vs InteractiveReply
InteractiveReply é o subconjunto interno mais antigo usado por helpers de aprovação e interação.
Ele oferece suporte a:
- texto
- botões
- selects
MessagePresentation é o contrato canônico compartilhado de envio. Ele adiciona:
- título
- tom
- contexto
- divisor
- botões somente com URL
- metadados genéricos de entrega por meio de
ReplyPayload.delivery
openclaw/plugin-sdk/interactive-runtime ao fazer bridge de
código mais antigo:
MessagePresentation diretamente.
Delivery Pin
Fixação é comportamento de entrega, não apresentação. Usedelivery.pin em vez de
campos nativos de provedor, como channelData.telegram.pin.
Semântica:
pin: truefixa a primeira mensagem entregue com sucesso.pin.notifyusafalsepor padrão.pin.requiredusafalsepor padrão.- Falhas opcionais de fixação sofrem degradação e deixam a mensagem enviada intacta.
- Falhas obrigatórias de fixação fazem a entrega falhar.
- Mensagens divididas em blocos fixam o primeiro bloco entregue, não o último.
pin, unpin e pins ainda existem para mensagens existentes
em que o provedor oferece suporte a essas operações.
Checklist para autores de Plugin
- Declare
presentationemdescribeMessageTool(...)quando o canal puder renderizar ou degradar com segurança a apresentação semântica. - Adicione
presentationCapabilitiesao adaptador de saída de runtime. - Implemente
renderPresentationem código de runtime, não em código de configuração de Plugin do plano de controle. - Mantenha bibliotecas nativas de UI fora de caminhos quentes de configuração/catálogo.
- Preserve limites de plataforma no renderizador e nos testes.
- Adicione testes de fallback para botões, selects, botões de URL, duplicação
de título/texto e envios mistos de
messagemaispresentation. - Adicione suporte a fixação de entrega por meio de
deliveryCapabilities.pinepinDeliveredMessagesomente quando o provedor puder fixar o ID da mensagem enviada. - Não exponha novos campos nativos de provedor para card/bloco/component/button pelo schema compartilhado de ação de mensagem.