Criando plugins de canal
Este guia mostra como criar um plugin de canal que conecta o OpenClaw a uma plataforma de mensagens. Ao final, você terá um canal funcional com segurança de DM, pareamento, encadeamento de respostas e envio de mensagens.Se você ainda não criou nenhum plugin do OpenClaw, leia primeiro
Primeiros passos para entender a estrutura básica
do pacote e a configuração do manifesto.
Como os plugins de canal funcionam
Plugins de canal não precisam de suas próprias ferramentas de enviar/editar/reagir. O OpenClaw mantém uma ferramentamessage compartilhada no core. Seu plugin é responsável por:
- Configuração — resolução de conta e assistente de configuração
- Segurança — política de DM e allowlists
- Pareamento — fluxo de aprovação de DM
- Gramática de sessão — como ids de conversa específicos do provedor são mapeados para chats base, ids de thread e fallbacks de pai
- Saída — envio de texto, mídia e enquetes para a plataforma
- Encadeamento — como as respostas são encadeadas
:thread: e pelo despacho.
Se a sua plataforma armazena escopo extra dentro de ids de conversa, mantenha esse parsing
no plugin com messaging.resolveSessionConversation(...). Esse é o
hook canônico para mapear rawId para o id base da conversa, id opcional
da thread, baseConversationId explícito e quaisquer parentConversationCandidates.
Ao retornar parentConversationCandidates, mantenha a ordem
do pai mais específico para o mais amplo/conversa base.
Plugins integrados que precisam do mesmo parsing antes de o registro do canal inicializar
também podem expor um arquivo session-key-api.ts de nível superior com um
export resolveSessionConversation(...) correspondente. O core usa essa superfície
segura para bootstrap apenas quando o registro de plugins em runtime ainda não está disponível.
messaging.resolveParentConversationCandidates(...) continua disponível como fallback legado de compatibilidade quando um plugin precisa apenas de fallbacks de pai sobre o id genérico/raw. Se ambos os hooks existirem, o core usa primeiro
resolveSessionConversation(...).parentConversationCandidates e só
recorre a resolveParentConversationCandidates(...) quando o hook canônico
os omite.
Aprovações e capacidades do canal
A maioria dos plugins de canal não precisa de código específico para aprovações.- O core é responsável por
/approveno mesmo chat, payloads compartilhados de botão de aprovação e entrega genérica de fallback. - Prefira um único objeto
approvalCapabilityno plugin de canal quando o canal precisar de comportamento específico de aprovação. ChannelPlugin.approvalsfoi removido. Coloque fatos de entrega/aprovação nativa/renderização/autenticação emapprovalCapability.plugin.authé apenas para login/logout; o core não lê mais hooks de autenticação de aprovação desse objeto.approvalCapability.authorizeActorActioneapprovalCapability.getActionAvailabilityStatesão a seam canônica de autenticação de aprovação.- Use
approvalCapability.getActionAvailabilityStatepara disponibilidade de autenticação de aprovação no mesmo chat. - Se o seu canal expõe aprovações nativas de exec, use
approvalCapability.getExecInitiatingSurfaceStatepara o estado da superfície iniciadora/cliente nativo quando ele diferir da autenticação de aprovação no mesmo chat. O core usa esse hook específico de exec para distinguirenableddedisabled, decidir se o canal iniciador oferece suporte a aprovações nativas de exec e incluir o canal nas orientações de fallback para cliente nativo.createApproverRestrictedNativeApprovalCapability(...)preenche isso para o caso comum. - Use
outbound.shouldSuppressLocalPayloadPromptououtbound.beforeDeliverPayloadpara comportamento específico do canal no ciclo de vida do payload, como ocultar prompts locais duplicados de aprovação ou enviar indicadores de digitação antes da entrega. - Use
approvalCapability.deliveryapenas para roteamento de aprovação nativa ou supressão de fallback. - Use
approvalCapability.nativeRuntimepara fatos de aprovação nativa sob responsabilidade do canal. Mantenha isso lazy em entrypoints quentes de canal comcreateLazyChannelApprovalNativeRuntimeAdapter(...), que pode importar seu módulo de runtime sob demanda e ainda permitir que o core monte o ciclo de vida da aprovação. - Use
approvalCapability.renderapenas quando um canal realmente precisar de payloads de aprovação personalizados em vez do renderizador compartilhado. - Use
approvalCapability.describeExecApprovalSetupquando o canal quiser que a resposta do caminho desativado explique os controles exatos de configuração necessários para ativar aprovações nativas de exec. O hook recebe{ channel, channelLabel, accountId }; canais com contas nomeadas devem renderizar caminhos com escopo de conta, comochannels.<channel>.accounts.<id>.execApprovals.*, em vez de padrões no nível superior. - Se um canal puder inferir identidades estáveis semelhantes a proprietário em DMs a partir da configuração existente, use
createResolvedApproverActionAuthAdapterdeopenclaw/plugin-sdk/approval-runtimepara restringir/approveno mesmo chat sem adicionar lógica específica de aprovação ao core. - Se um canal precisar de entrega nativa de aprovação, mantenha o código do canal focado em normalização de destino mais fatos de transporte/apresentação. Use
createChannelExecApprovalProfile,createChannelNativeOriginTargetResolver,createChannelApproverDmTargetResolverecreateApproverRestrictedNativeApprovalCapabilitydeopenclaw/plugin-sdk/approval-runtime. Coloque os fatos específicos do canal atrás deapprovalCapability.nativeRuntime, idealmente por meio decreateChannelApprovalNativeRuntimeAdapter(...)oucreateLazyChannelApprovalNativeRuntimeAdapter(...), para que o core possa montar o handler e assumir filtro de requisições, roteamento, deduplicação, expiração, assinatura do gateway e avisos de redirecionamento.nativeRuntimeé dividido em algumas seams menores: availability— se a conta está configurada e se uma requisição deve ser tratadapresentation— mapeia o view model compartilhado de aprovação para payloads nativos pendentes/resolvidos/expirados ou ações finaistransport— prepara destinos e envia/atualiza/exclui mensagens nativas de aprovaçãointeractions— hooks opcionais de bind/unbind/clear-action para botões ou reações nativasobserve— hooks opcionais de diagnóstico de entrega- Se o canal precisar de objetos sob responsabilidade do runtime, como um client, token, app Bolt ou receptor de webhook, registre-os por meio de
openclaw/plugin-sdk/channel-runtime-context. O registro genérico de contexto de runtime permite que o core inicialize handlers orientados por capacidade a partir do estado de inicialização do canal sem adicionar glue wrapper específico de aprovação. - Recorra ao nível mais baixo de
createChannelApprovalHandleroucreateChannelNativeApprovalRuntimeapenas quando a seam orientada por capacidade ainda não for suficientemente expressiva. - Canais de aprovação nativa devem rotear
accountIdeapprovalKindpor esses helpers.accountIdmantém a política de aprovação multi-account no escopo correto da conta do bot, eapprovalKindmantém o comportamento de aprovação de exec versus plugin disponível para o canal sem branches hardcoded no core. - O core agora também é responsável pelos avisos de redirecionamento de aprovação. Plugins de canal não devem enviar suas próprias mensagens de acompanhamento do tipo “a aprovação foi para DMs / outro canal” a partir de
createChannelNativeApprovalRuntime; em vez disso, exponha roteamento preciso de origem + DM do aprovador por meio dos helpers compartilhados de capacidade de aprovação e deixe o core agregar as entregas reais antes de publicar qualquer aviso de volta no chat iniciador. - Preserve o tipo de id de aprovação entregue de ponta a ponta. Clientes nativos não devem adivinhar nem reescrever o roteamento de aprovação de exec versus plugin a partir de estado local do canal.
- Diferentes tipos de aprovação podem expor intencionalmente superfícies nativas diferentes.
Exemplos integrados atuais:
- O Slack mantém o roteamento de aprovação nativa disponível tanto para ids de exec quanto de plugin.
- O Matrix mantém o mesmo roteamento nativo de DM/canal e UX de reação para aprovações de exec e plugin, ao mesmo tempo em que ainda permite que a autenticação varie por tipo de aprovação.
createApproverRestrictedNativeApprovalAdapterainda existe como wrapper de compatibilidade, mas código novo deve preferir o construtor de capability e exporapprovalCapabilityno plugin.
openclaw/plugin-sdk/approval-auth-runtimeopenclaw/plugin-sdk/approval-client-runtimeopenclaw/plugin-sdk/approval-delivery-runtimeopenclaw/plugin-sdk/approval-gateway-runtimeopenclaw/plugin-sdk/approval-handler-adapter-runtimeopenclaw/plugin-sdk/approval-handler-runtimeopenclaw/plugin-sdk/approval-native-runtimeopenclaw/plugin-sdk/approval-reply-runtimeopenclaw/plugin-sdk/channel-runtime-context
openclaw/plugin-sdk/setup-runtime,
openclaw/plugin-sdk/setup-adapter-runtime,
openclaw/plugin-sdk/reply-runtime,
openclaw/plugin-sdk/reply-dispatch-runtime,
openclaw/plugin-sdk/reply-reference e
openclaw/plugin-sdk/reply-chunking quando você não precisar da
superfície mais ampla.
Especificamente para setup:
openclaw/plugin-sdk/setup-runtimecobre os helpers de setup seguros para runtime: adaptadores de patch de setup seguros para importação (createPatchedAccountSetupAdapter,createEnvPatchedAccountSetupAdapter,createSetupInputPresenceValidator), saída de nota de lookup,promptResolvedAllowFrom,splitSetupEntriese os builders delegados de proxy de setupopenclaw/plugin-sdk/setup-adapter-runtimeé a seam estreita de adaptador com suporte a env paracreateEnvPatchedAccountSetupAdapteropenclaw/plugin-sdk/channel-setupcobre os builders de setup com instalação opcional mais alguns primitivos seguros para setup:createOptionalChannelSetupSurface,createOptionalChannelSetupAdapter,
channelEnvVars. Mantenha envVars do runtime do canal ou constantes locais apenas para cópia voltada ao operador.
createOptionalChannelSetupWizard, DEFAULT_ACCOUNT_ID,
createTopLevelChannelDmPolicy, setSetupChannelEnabled e
splitSetupEntries
- use a seam mais ampla
openclaw/plugin-sdk/setupapenas quando também precisar dos helpers compartilhados mais pesados de setup/configuração, comomoveSingleAccountChannelSectionToDefaultAccount(...)
createOptionalChannelSetupSurface(...). O adaptador/assistente gerado falha de forma fechada em gravações de configuração e finalização, e reutiliza a mesma mensagem de instalação obrigatória em validação, finalização e cópia de links de documentação.
Para outros caminhos quentes de canal, prefira os helpers estreitos em vez de superfícies legadas mais amplas:
openclaw/plugin-sdk/account-core,openclaw/plugin-sdk/account-id,openclaw/plugin-sdk/account-resolutioneopenclaw/plugin-sdk/account-helperspara configuração multi-account e fallback de conta padrãoopenclaw/plugin-sdk/inbound-envelopeeopenclaw/plugin-sdk/inbound-reply-dispatchpara rota/envelope de entrada e wiring de registrar e despacharopenclaw/plugin-sdk/messaging-targetspara parsing/correspondência de destinosopenclaw/plugin-sdk/outbound-mediaeopenclaw/plugin-sdk/outbound-runtimepara carregamento de mídia mais delegados de identidade/envio de saídaopenclaw/plugin-sdk/thread-bindings-runtimepara ciclo de vida de thread-binding e registro de adaptadoropenclaw/plugin-sdk/agent-media-payloadapenas quando ainda for necessário um layout legado de campo de payload de agente/mídiaopenclaw/plugin-sdk/telegram-command-configpara normalização de comandos personalizados do Telegram, validação de duplicatas/conflitos e um contrato estável de fallback para configuração de comandos
Política de menção de entrada
Mantenha o tratamento de menções de entrada dividido em duas camadas:- coleta de evidências sob responsabilidade do plugin
- avaliação compartilhada de política
openclaw/plugin-sdk/channel-inbound para a camada compartilhada.
Bom ajuste para lógica local do plugin:
- detecção de resposta ao bot
- detecção de citação do bot
- verificações de participação em thread
- exclusões de mensagens de serviço/sistema
- caches nativos da plataforma necessários para comprovar a participação do bot
requireMention- resultado explícito de menção
- allowlist de menção implícita
- bypass de comando
- decisão final de ignorar
- Calcule os fatos locais de menção.
- Passe esses fatos para
resolveInboundMentionDecision({ facts, policy }). - Use
decision.effectiveWasMentioned,decision.shouldBypassMentionedecision.shouldSkipno seu gate de entrada.
api.runtime.channel.mentions expõe os mesmos helpers compartilhados de menção para
plugins de canal integrados que já dependem de injeção em runtime:
buildMentionRegexesmatchesMentionPatternsmatchesMentionWithExplicitimplicitMentionKindWhenresolveInboundMentionDecision
resolveMentionGating* permanecem em
openclaw/plugin-sdk/channel-inbound apenas como exports de compatibilidade. Código novo
deve usar resolveInboundMentionDecision({ facts, policy }).
Passo a passo
Pacote e manifesto
Crie os arquivos padrão do plugin. O campo
channel em package.json é
o que faz deste um plugin de canal. Para a superfície completa de metadados
do pacote, veja Setup e configuração de plugins:Crie o objeto do plugin de canal
A interface
ChannelPlugin tem muitas superfícies opcionais de adaptador. Comece com
o mínimo — id e setup — e adicione adaptadores conforme necessário.Crie src/channel.ts:src/channel.ts
O que `createChatChannelPlugin` faz por você
O que `createChatChannelPlugin` faz por você
Em vez de implementar manualmente interfaces de adaptador de baixo nível, você passa
opções declarativas e o builder compõe tudo:
Você também pode passar objetos brutos de adaptador em vez de opções declarativas
se precisar de controle total.
| Option | O que ele conecta |
|---|---|
security.dm | Resolver de segurança de DM com escopo a partir de campos de configuração |
pairing.text | Fluxo de pareamento de DM baseado em texto com troca de código |
threading | Resolver do modo reply-to (fixo, com escopo de conta ou personalizado) |
outbound.attachedResults | Funções de envio que retornam metadados do resultado (ids de mensagem) |
Conecte o ponto de entrada
Crie Coloque descritores de CLI sob responsabilidade do canal em
index.ts:index.ts
registerCliMetadata(...) para que o OpenClaw
possa mostrá-los na ajuda raiz sem ativar o runtime completo do canal,
enquanto carregamentos completos normais ainda capturam os mesmos descritores para o registro real de comandos.
Mantenha registerFull(...) para trabalho apenas de runtime.
Se registerFull(...) registrar métodos RPC do gateway, use um
prefixo específico do plugin. Namespaces de administração do core (config.*,
exec.approvals.*, wizard.*, update.*) permanecem reservados e sempre
resolvem para operator.admin.
defineChannelPluginEntry lida automaticamente com a separação entre modos de registro. Veja
Pontos de entrada para todas as
opções.Adicione uma entrada de setup
Crie O OpenClaw carrega isso em vez da entrada completa quando o canal está desativado
ou não configurado. Isso evita puxar código pesado de runtime durante fluxos de setup.
Veja Setup e configuração para detalhes.
setup-entry.ts para carregamento leve durante o onboarding:setup-entry.ts
Lide com mensagens de entrada
Seu plugin precisa receber mensagens da plataforma e encaminhá-las para
o OpenClaw. O padrão típico é um webhook que verifica a requisição e
a despacha por meio do handler de entrada do seu canal:
O tratamento de mensagens de entrada é específico de cada canal. Cada plugin de canal é responsável
pelo seu próprio pipeline de entrada. Veja plugins de canal integrados
(por exemplo, o pacote de plugin do Microsoft Teams ou do Google Chat) para padrões reais.
Teste
Escreva testes colocados junto do código em Para helpers de teste compartilhados, veja Testes.
src/channel.test.ts:src/channel.test.ts
Estrutura de arquivos
Tópicos avançados
Opções de encadeamento
Modos de resposta fixos, com escopo de conta ou personalizados
Integração da ferramenta de mensagem
describeMessageTool e descoberta de ações
Resolução de destino
inferTargetChatType, looksLikeId, resolveTarget
Helpers de runtime
TTS, STT, mídia, subagente via api.runtime
Algumas seams auxiliares integradas ainda existem para manutenção de bundled-plugin e
compatibilidade. Elas não são o padrão recomendado para novos plugins de canal;
prefira os subcaminhos genéricos de channel/setup/reply/runtime da superfície
comum do SDK, a menos que você esteja mantendo diretamente essa família de bundled plugin.
Próximos passos
- Plugins de provedor — se o seu plugin também fornece modelos
- Visão geral do SDK — referência completa de imports por subcaminho
- Testes do SDK — utilitários de teste e testes de contrato
- Manifesto de plugin — esquema completo do manifesto