- seções de texto
- pequeno texto de contexto/rodapé
- divisores
- botões
- menus de seleção
- título e tom do cartão
components, Slack
blocks, Telegram buttons, Teams card ou Feishu card, à ferramenta
compartilhada de mensagens. Esses são resultados de renderização pertencentes ao plugin de canal.
Contrato
Autores de plugins importam o contrato público de:action.type: "command"executa um comando de barra nativo pelo caminho de comandos do núcleo. Use isso para botões e menus de comandos integrados.action.type: "callback"transporta dados opacos do plugin pelo caminho de interação do canal. Plugins de canal não devem reinterpretar dados de callback como comandos de barra.valueé o valor opaco de callback legado. Novos controles devem usaractionpara que plugins de canal possam mapear comandos e callbacks sem inferir pelo texto.urlé um botão de link. Ele pode existir semvalue.webAppdescreve um botão de aplicativo web nativo do canal. O Telegram renderiza isso comoweb_appe oferece suporte apenas em chats privados.web_appainda é aceito em payloads JSON flexíveis por compatibilidade, mas produtores TypeScript devem usarwebApp.labelé obrigatório e também é usado no fallback de texto.styleé consultivo. Renderizadores devem mapear estilos sem suporte para um padrão seguro, sem falhar o envio.priorityé opcional. Quando um canal anuncia limites de ação e controles precisam ser removidos, o núcleo mantém primeiro os botões de maior prioridade e preserva a ordem original entre botões de prioridade igual. Quando todos os controles cabem, a ordem definida pelo autor é preservada.disabledé opcional. Canais devem optar explicitamente comsupportsDisabled; caso contrário, o núcleo degrada o controle desativado para texto de fallback não interativo.reusableé opcional. Canais que oferecem suporte a callbacks nativos reutilizáveis podem manter a ação disponível após uma interação bem-sucedida. Use para ações repetíveis ou idempotentes, como atualizar, inspecionar ou ver mais detalhes; deixe indefinido para aprovações normais de uso único e ações destrutivas.
options[].actiontem o mesmo significado de comando/callback queactionde botão.options[].valueé o valor legado da aplicação selecionada.placeholderé consultivo e pode ser ignorado por canais sem suporte nativo a seleção.- Se um canal não oferece suporte a seleções, o texto de fallback lista os rótulos.
Exemplos de produtores
Cartão simples:Contrato do renderizador
Plugins de canal declaram suporte de renderização no adaptador de saída:limits
opcionais descrevem o envelope genérico que o núcleo pode adaptar antes de chamar o
renderizador:
Fluxo de renderização do núcleo
Quando umReplyPayload ou ação de mensagem inclui presentation, o núcleo:
- Normaliza o payload de apresentação.
- Resolve o adaptador de saída do canal de destino.
- Lê
presentationCapabilities. - Aplica limites genéricos de capacidade, como contagem de ações, comprimento de rótulo e contagem de opções de seleção quando o adaptador os anuncia.
- Chama
renderPresentationquando o adaptador consegue renderizar o payload. - Faz fallback para 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 enviar em canais limitados. O texto de fallback inclui:titlecomo a primeira linha- blocos
textcomo parágrafos normais - blocos
contextcomo linhas compactas de contexto - blocos
dividercomo separador visual - rótulos de botões, incluindo URLs para botões de link
- rótulos de opções de seleção
Visibilidade de fallback de valores de botão
Quando um canal não consegue renderizar controles interativos, valores de botões e seleções fazem fallback para texto simples. O comportamento de fallback preserva a usabilidade enquanto mantém privados os dados opacos de callback:- Ações tipadas como
commandsão renderizadas comolabel: \command“ para que usuários possam copiar o comando e executá-lo manualmente na entrada do canal. - Ações tipadas como
callbacke campos legadosvaluesão renderizados como apenas rótulo. O valor opaco de callback não é exposto no texto de fallback. - Botões
url/webApprenderizam o texto da URL junto com o rótulo do botão, já que a URL é voltada ao usuário. - Opções de seleção são renderizadas apenas como rótulo. O valor de opção subjacente não é exposto no texto de fallback.
- Telegram com botões inline desativados envia fallback de texto.
- Um canal sem suporte a seleção lista opções de seleção como texto.
- Um botão somente URL se torna um botão de link nativo ou uma linha de URL de 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 conseguir fixar a mensagem enviada, a entrega reporta falha.
Mapeamento de provedores
Renderizadores integrados atuais:| Canal | Destino de renderização nativo | Observações |
|---|---|---|
| Discord | Componentes e contêineres de componentes | Preserva channelData.discord.components legado para produtores de payloads nativos de provedor existentes, mas novos envios compartilhados devem usar presentation. |
| Slack | Block Kit | Preserva channelData.slack.blocks legado para produtores de payloads nativos de provedor existentes, mas novos envios compartilhados devem usar presentation. |
| Telegram | Texto mais teclados inline | Botões/seletores exigem capacidade de botão inline para a superfície de destino; caso contrário, o fallback de texto é usado. |
| Mattermost | Texto mais props interativas | Outros blocos degradam para texto. |
| Microsoft Teams | Adaptive Cards | O texto simples de message é incluído com o cartão quando ambos são fornecidos. |
| Feishu | Cartões interativos | O cabeçalho do cartão pode usar title; o corpo evita duplicar esse título. |
| Canais simples | Fallback de texto | Canais sem renderizador ainda recebem uma saída legível. |
Presentation vs InteractiveReply
InteractiveReply é o subconjunto interno mais antigo usado por auxiliares de aprovação e interação.
Ele oferece suporte a:
- texto
- botões
- seletores
MessagePresentation é o contrato canônico de envio compartilhado. Ele adiciona:
- título
- tom
- contexto
- divisor
- botões somente de URL
- metadados genéricos de entrega por meio de
ReplyPayload.delivery
openclaw/plugin-sdk/interactive-runtime ao fazer a ponte com código mais antigo:
OC_I18N_900011
Código novo deve aceitar ou produzir MessagePresentation diretamente. Payloads
interactive existentes são um subconjunto obsoleto de presentation; o suporte
em runtime permanece para produtores mais antigos.
Os tipos InteractiveReply* legados e auxiliares de conversão estão marcados como
@deprecated no SDK:
InteractiveReply,InteractiveReplyBlock,InteractiveReplyButton,InteractiveReplyOption,InteractiveReplySelectBlockeInteractiveReplyTextBlocknormalizeInteractiveReply(...)hasInteractiveReplyBlocks(...)interactiveReplyToPresentation(...)presentationToInteractiveReply(...)presentationToInteractiveControlsReply(...)resolveInteractiveTextFallback(...)reduceInteractiveReply(...)
presentationToInteractiveReply(...) e
presentationToInteractiveControlsReply(...) continuam disponíveis como pontes de renderizador
para implementações legadas de canal. Código novo de produtor não deve chamá-los;
envie presentation e deixe a adaptação do core/canal cuidar da renderização.
Os auxiliares de aprovação também têm substitutos que priorizam presentation:
- use
buildApprovalPresentationFromActionDescriptors(...)em vez debuildApprovalInteractiveReplyFromActionDescriptors(...) - use
buildApprovalPresentation(...)em vez debuildApprovalInteractiveReply(...) - use
buildExecApprovalPresentation(...)em vez debuildExecApprovalInteractiveReply(...)
renderMessagePresentationFallbackText(...) retorna uma string vazia para blocos de
presentation que não têm fallback de texto, como uma presentation contendo apenas divisor.
Transportes que exigem um corpo de envio não vazio podem passar
emptyFallback para optar por um corpo mínimo sem alterar o contrato padrão de fallback.
Fixação de entrega
Fixar é comportamento de entrega, não presentation. Usedelivery.pin em vez de
campos nativos de provedor como channelData.telegram.pin.
Semântica:
pin: truefixa a primeira mensagem entregue com sucesso.pin.notifyusafalsecomo padrão.pin.requiredusafalsecomo padrão.- Falhas opcionais de fixação degradam e deixam a mensagem enviada intacta.
- Falhas obrigatórias de fixação fazem a entrega falhar.
- Mensagens em chunks fixam o primeiro chunk entregue, não o chunk final.
pin, unpin e pins ainda existem para mensagens
existentes em que o provedor oferece suporte a essas operações.
Checklist de autor de Plugin
- Declare
presentationa partir dedescribeMessageTool(...)quando o canal puder renderizar ou degradar com segurança a apresentação semântica. - Adicione
presentationCapabilitiesao adaptador de saída do runtime. - Implemente
renderPresentationno código de runtime, não no código de configuração de Plugin do plano de controle. - Mantenha bibliotecas de UI nativas fora dos caminhos quentes de setup/catálogo.
- Declare limites genéricos de capacidade em
presentationCapabilities.limitsquando eles forem conhecidos. - Preserve os limites finais da plataforma no renderizador e nos testes.
- Adicione testes de fallback para botões sem suporte, seletores, 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 de cartão/bloco/componente/botão por meio do schema compartilhado de ação de mensagem.