Microsoft Teams (plugin)
“Abandonai toda esperança, vós que entrais aqui.”Atualizado: 2026-01-21 Status: texto + anexos em DMs são suportados; envio de arquivos em canais/grupos requer
sharePointSiteId + permissões do Graph (veja Envio de arquivos em chats em grupo). Enquetes são enviadas via Adaptive Cards.
Plugin necessário
O Microsoft Teams é distribuído como um plugin e não vem incluído na instalação principal. Mudança incompatível (2026.1.15): o MS Teams saiu do core. Se você usa, é necessário instalar o plugin. Justificativa: mantém as instalações do core mais leves e permite que as dependências do MS Teams sejam atualizadas de forma independente. Instalação via CLI (registro npm):Configuração rápida (iniciante)
- Instale o plugin do Microsoft Teams.
- Crie um Azure Bot (App ID + client secret + tenant ID).
- Configure o OpenClaw com essas credenciais.
- Exponha
/api/messages(porta 3978 por padrão) via uma URL pública ou túnel. - Instale o pacote do app do Teams e inicie o gateway.
channels.msteams.groupPolicy: "allowlist"). Para permitir respostas em grupo, defina channels.msteams.groupAllowFrom (ou use groupPolicy: "open" para permitir qualquer membro, com exigência de menção).
Objetivos
- Conversar com o OpenClaw via DMs do Teams, chats em grupo ou canais.
- Manter o roteamento determinístico: as respostas sempre retornam ao canal de origem.
- Padrão para comportamento seguro em canais (menções obrigatórias, salvo configuração em contrário).
Escritas de configuração
Por padrão, o Microsoft Teams tem permissão para escrever atualizações de configuração acionadas por/config set|unset (requer commands.config: true).
Desative com:
Controle de acesso (DMs + grupos)
Acesso por DM- Padrão:
channels.msteams.dmPolicy = "pairing". Remetentes desconhecidos são ignorados até aprovação. channels.msteams.allowFromaceita IDs de objeto do AAD, UPNs ou nomes de exibição. O assistente resolve nomes para IDs via Microsoft Graph quando as credenciais permitem.
- Padrão:
channels.msteams.groupPolicy = "allowlist"(bloqueado a menos que você adicionegroupAllowFrom). Usechannels.defaults.groupPolicypara substituir o padrão quando não definido. channels.msteams.groupAllowFromcontrola quais remetentes podem acionar em chats/canais de grupo (retorna parachannels.msteams.allowFrom).- Defina
groupPolicy: "open"para permitir qualquer membro (ainda com exigência de menção por padrão). - Para permitir nenhum canal, defina
channels.msteams.groupPolicy: "disabled".
- Delimite respostas de grupo/canal listando equipes e canais em
channels.msteams.teams. - As chaves podem ser IDs ou nomes de equipes; as chaves de canal podem ser IDs de conversa ou nomes.
- Quando
groupPolicy="allowlist"e uma lista de permissões de equipes estiver presente, apenas as equipes/canais listados são aceitos (com exigência de menção). - O assistente de configuração aceita entradas
Team/Channele as armazena para você. - Na inicialização, o OpenClaw resolve nomes de equipes/canais e listas de permissões de usuários para IDs (quando as permissões do Graph permitem) e registra o mapeamento; entradas não resolvidas são mantidas como digitadas.
Como funciona
- Instale o plugin do Microsoft Teams.
- Crie um Azure Bot (App ID + secret + tenant ID).
- Crie um pacote de app do Teams que referencie o bot e inclua as permissões RSC abaixo.
- Envie/instale o app do Teams em uma equipe (ou escopo pessoal para DMs).
- Configure
msteamsem~/.openclaw/openclaw.json(ou variáveis de ambiente) e inicie o gateway. - O gateway escuta o tráfego de webhook do Bot Framework em
/api/messagespor padrão.
Configuração do Azure Bot (Pré-requisitos)
Antes de configurar o OpenClaw, você precisa criar um recurso Azure Bot.Etapa 1: Criar Azure Bot
- Acesse Create Azure Bot
-
Preencha a aba Basics:
Campo Valor Identificador do bot Nome do seu bot, ex.: openclaw-msteams(deve ser único)Assinatura Selecione sua assinatura do Azure Grupo de recursos Crie um novo ou use um existente Nível de preço Free para dev/testes Tipo de aplicativo Single Tenant (recomendado — veja a nota abaixo) Tipo de criação Criar novo Microsoft App ID
Aviso de descontinuação: a criação de novos bots multi-tenant foi descontinuada após 2025-07-31. Use Single Tenant para novos bots.
- Clique em Review + create → Create (aguarde ~1–2 minutos)
Etapa 2: Obter credenciais
- Vá ao recurso Azure Bot → Configuration
- Copie Microsoft App ID → este é seu
appId - Clique em Manage Password → vá para o App Registration
- Em Certificates & secrets → New client secret → copie o Value → este é seu
appPassword - Vá em Overview → copie Directory (tenant) ID → este é seu
tenantId
Etapa 3: Configurar o endpoint de mensagens
- No Azure Bot → Configuration
- Defina Messaging endpoint para a URL do seu webhook:
- Produção:
https://your-domain.com/api/messages - Dev local: use um túnel (veja Desenvolvimento local abaixo)
- Produção:
Etapa 4: Habilitar o canal Teams
- No Azure Bot → Channels
- Clique em Microsoft Teams → Configure → Save
- Aceite os Termos de Serviço
Desenvolvimento local (Tunneling)
O Teams não consegue alcançarlocalhost. Use um túnel para desenvolvimento local:
Opção A: ngrok
Teams Developer Portal (Alternativa)
Em vez de criar manualmente um ZIP de manifesto, você pode usar o Teams Developer Portal:- Clique em + New app
- Preencha as informações básicas (nome, descrição, informações do desenvolvedor)
- Vá em App features → Bot
- Selecione Enter a bot ID manually e cole o App ID do seu Azure Bot
- Marque os escopos: Personal, Team, Group Chat
- Clique em Distribute → Download app package
- No Teams: Apps → Manage your apps → Upload a custom app → selecione o ZIP
Testando o bot
Opção A: Azure Web Chat (verifique o webhook primeiro)- No Azure Portal → seu recurso Azure Bot → Test in Web Chat
- Envie uma mensagem — você deve ver uma resposta
- Isso confirma que o endpoint do webhook funciona antes da configuração do Teams
- Instale o app do Teams (sideload ou catálogo da organização)
- Encontre o bot no Teams e envie uma DM
- Verifique os logs do gateway para atividade de entrada
Configuração (mínima, apenas texto)
-
Instalar o plugin do Microsoft Teams
- Do npm:
openclaw plugins install @openclaw/msteams - De um checkout local:
openclaw plugins install ./extensions/msteams
- Do npm:
-
Registro do bot
- Crie um Azure Bot (veja acima) e anote:
- ID do aplicativo
- Client secret (senha do app)
- Tenant ID (single-tenant)
- Crie um Azure Bot (veja acima) e anote:
-
Manifesto do app do Teams
- Inclua uma entrada
botcombotId = <App ID>. - Escopos:
personal,team,groupChat. supportsFiles: true(necessário para manipulação de arquivos no escopo pessoal).- Adicione permissões RSC (abaixo).
- Crie ícones:
outline.png(32x32) ecolor.png(192x192). - Compacte os três arquivos juntos:
manifest.json,outline.png,color.png.
- Inclua uma entrada
-
Configurar o OpenClaw
Você também pode usar variáveis de ambiente em vez de chaves de configuração:
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
-
Endpoint do bot
- Defina o Messaging Endpoint do Azure Bot para:
https://<host>:3978/api/messages(ou o caminho/porta escolhidos).
- Defina o Messaging Endpoint do Azure Bot para:
-
Executar o gateway
- O canal do Teams inicia automaticamente quando o plugin está instalado e existe a configuração
msteamscom credenciais.
- O canal do Teams inicia automaticamente quando o plugin está instalado e existe a configuração
Contexto de histórico
channels.msteams.historyLimitcontrola quantas mensagens recentes de canal/grupo são incluídas no prompt.- Retorna para
messages.groupChat.historyLimit. Defina0para desativar (padrão 50). - O histórico de DMs pode ser limitado com
channels.msteams.dmHistoryLimit(turnos por usuário). Substituições por usuário:channels.msteams.dms["<user_id>"].historyLimit.
Permissões RSC atuais do Teams (Manifesto)
Estas são as permissões resourceSpecific existentes no manifesto do nosso app do Teams. Elas só se aplicam dentro da equipe/chat onde o app está instalado. Para canais (escopo de equipe):ChannelMessage.Read.Group(Application) - receber todas as mensagens do canal sem @mençãoChannelMessage.Send.Group(Application)Member.Read.Group(Application)Owner.Read.Group(Application)ChannelSettings.Read.Group(Application)TeamMember.Read.Group(Application)TeamSettings.Read.Group(Application)
ChatMessage.Read.Chat(Application) - receber todas as mensagens do chat em grupo sem @menção
Exemplo de manifesto do Teams (redigido)
Exemplo mínimo e válido com os campos obrigatórios. Substitua IDs e URLs.Observações do manifesto (campos obrigatórios)
bots[].botIddeve corresponder exatamente ao App ID do Azure Bot.webApplicationInfo.iddeve corresponder ao App ID do Azure Bot.bots[].scopesdeve incluir as superfícies que você pretende usar (personal,team,groupChat).bots[].supportsFiles: trueé obrigatório para manipulação de arquivos no escopo pessoal.authorization.permissions.resourceSpecificdeve incluir leitura/envio de canal se você quiser tráfego de canal.
Atualizando um app existente
Para atualizar um app do Teams já instalado (por exemplo, para adicionar permissões RSC):- Atualize seu
manifest.jsoncom as novas configurações - Incremente o campo
version(ex.:1.0.0→1.1.0) - Recompacte o manifesto com os ícones (
manifest.json,outline.png,color.png) - Envie o novo zip:
- Opção A (Teams Admin Center): Teams Admin Center → Teams apps → Manage apps → encontre seu app → Upload new version
- Opção B (Sideload): No Teams → Apps → Manage your apps → Upload a custom app
- Para canais de equipe: reinstale o app em cada equipe para que as novas permissões entrem em vigor
- Feche completamente e reabra o Teams (não apenas fechar a janela) para limpar o cache de metadados do app
Capacidades: apenas RSC vs Graph
Com apenas Teams RSC (app instalado, sem permissões da Graph API)
Funciona:- Ler conteúdo de texto de mensagens de canal.
- Enviar conteúdo de texto para canais.
- Receber anexos de arquivos pessoais (DM).
- Conteúdo de imagem ou arquivo em canais/grupos (o payload inclui apenas um stub HTML).
- Download de anexos armazenados no SharePoint/OneDrive.
- Leitura de histórico de mensagens (além do evento de webhook ao vivo).
Com Teams RSC + permissões de Aplicação do Microsoft Graph
Adiciona:- Download de conteúdos hospedados (imagens coladas em mensagens).
- Download de anexos de arquivos armazenados no SharePoint/OneDrive.
- Leitura de histórico de mensagens de canal/chat via Graph.
RSC vs Graph API
| Capacidade | Permissões RSC | Graph API |
|---|---|---|
| Mensagens em tempo real | Sim (via webhook) | Não (apenas polling) |
| Mensagens históricas | Não | Sim (pode consultar histórico) |
| Complexidade de setup | Apenas manifesto do app | Requer consentimento admin + fluxo de token |
| Funciona offline | Não (precisa estar rodando) | Sim (consultar a qualquer momento) |
ChannelMessage.Read.All (requer consentimento de administrador).
Mídia + histórico habilitados por Graph (necessário para canais)
Se você precisa de imagens/arquivos em canais ou quer buscar histórico de mensagens, é necessário habilitar permissões do Microsoft Graph e conceder consentimento de administrador.- No Entra ID (Azure AD) App Registration, adicione permissões de Application do Microsoft Graph:
ChannelMessage.Read.All(anexos de canal + histórico)Chat.Read.AllouChatMessage.Read.All(chats em grupo)
- Conceda consentimento de administrador para o tenant.
- Aumente a versão do manifesto do app do Teams, reenvie e reinstale o app no Teams.
- Feche completamente e reabra o Teams para limpar o cache de metadados do app.
User.Read.All (Application) e conceda consentimento de administrador.
Limitações conhecidas
Timeouts de webhook
O Teams entrega mensagens via webhook HTTP. Se o processamento demorar muito (por exemplo, respostas lentas de LLM), você pode ver:- Timeouts do gateway
- O Teams tentando reenviar a mensagem (causando duplicatas)
- Respostas perdidas
Formatação
O markdown do Teams é mais limitado que o do Slack ou Discord:- Formatação básica funciona: negrito, itálico,
code, links - Markdown complexo (tabelas, listas aninhadas) pode não renderizar corretamente
- Adaptive Cards são suportados para enquetes e envio arbitrário de cards (veja abaixo)
Configuração
Principais configurações (veja/gateway/configuration para padrões compartilhados entre canais):
channels.msteams.enabled: habilitar/desabilitar o canal.channels.msteams.appId,channels.msteams.appPassword,channels.msteams.tenantId: credenciais do bot.channels.msteams.webhook.port(padrão3978)channels.msteams.webhook.path(padrão/api/messages)channels.msteams.dmPolicy:pairing | allowlist | open | disabled(padrão: pareamento)channels.msteams.allowFrom: lista de permissões para DMs (IDs de objeto do AAD, UPNs ou nomes de exibição). O assistente resolve nomes para IDs durante a configuração quando há acesso ao Graph.channels.msteams.textChunkLimit: tamanho do bloco de texto de saída.channels.msteams.chunkMode:length(padrão) ounewlinepara dividir em linhas em branco (limites de parágrafo) antes do particionamento por comprimento.channels.msteams.mediaAllowHosts: lista de permissões para hosts de anexos de entrada (padrão para domínios Microsoft/Teams).channels.msteams.mediaAuthAllowHosts: lista de permissões para anexar cabeçalhos Authorization em tentativas de mídia (padrão para hosts do Graph + Bot Framework).channels.msteams.requireMention: exigir @menção em canais/grupos (padrão true).channels.msteams.replyStyle:thread | top-level(veja Estilo de resposta).channels.msteams.teams.<teamId>.replyStyle: substituição por equipe.channels.msteams.teams.<teamId>.requireMention: substituição por equipe.channels.msteams.teams.<teamId>.tools: substituições padrão de política de ferramentas por equipe (allow/deny/alsoAllow) usadas quando falta uma substituição por canal.channels.msteams.teams.<teamId>.toolsBySender: substituições padrão de política de ferramentas por equipe e por remetente ("*"com curinga suportado).channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: substituição por canal.channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: substituição por canal.channels.msteams.teams.<teamId>.channels.<conversationId>.tools: substituições de política de ferramentas por canal (allow/deny/alsoAllow).channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: substituições de política de ferramentas por canal e por remetente ("*"com curinga suportado).channels.msteams.sharePointSiteId: ID do site do SharePoint para uploads de arquivos em chats/canais de grupo (veja Envio de arquivos em chats em grupo).
Roteamento e sessões
- As chaves de sessão seguem o formato padrão do agente (veja /concepts/session):
- Mensagens diretas compartilham a sessão principal (
agent:<agentId>:<mainKey>). - Mensagens de canal/grupo usam o id da conversa:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- Mensagens diretas compartilham a sessão principal (
Estilo de resposta: Threads vs Posts
O Teams introduziu recentemente dois estilos de UI de canal sobre o mesmo modelo de dados subjacente:| Estilo | Descrição | replyStyle recomendado |
|---|---|---|
| Posts (clássico) | Mensagens aparecem como cards com respostas em thread abaixo | thread (padrão) |
| Threads (estilo Slack) | Mensagens fluem linearmente, mais como o Slack | top-level |
replyStyle errado:
threadem um canal no estilo Threads → respostas aparecem aninhadas de forma estranhatop-levelem um canal no estilo Posts → respostas aparecem como posts de nível superior separados, em vez de em thread
replyStyle por canal com base em como o canal está configurado:
Anexos e imagens
Limitações atuais:- DMs: imagens e anexos de arquivos funcionam via APIs de arquivos do bot do Teams.
- Canais/grupos: anexos ficam no armazenamento do M365 (SharePoint/OneDrive). O payload do webhook inclui apenas um stub HTML, não os bytes reais do arquivo. Permissões da Graph API são necessárias para baixar anexos de canais.
channels.msteams.mediaAllowHosts (use ["*"] para permitir qualquer host).
Cabeçalhos de autorização são anexados apenas para hosts em channels.msteams.mediaAuthAllowHosts (padrão para hosts do Graph + Bot Framework). Mantenha esta lista restrita (evite sufixos multi-tenant).
Envio de arquivos em chats em grupo
Bots podem enviar arquivos em DMs usando o fluxo FileConsentCard (integrado). No entanto, enviar arquivos em chats/canais de grupo requer configuração adicional:| Contexto | Como os arquivos são enviados | Configuração necessária |
|---|---|---|
| DMs | FileConsentCard → usuário aceita → bot envia | Funciona fora da caixa |
| Chats/canais de grupo | Upload no SharePoint → link de compartilhamento | Requer sharePointSiteId + permissões do Graph |
| Imagens (qualquer contexto) | Inline codificado em Base64 | Funciona fora da caixa |
Por que chats em grupo precisam do SharePoint
Bots não têm um drive pessoal do OneDrive (o endpoint da Graph API/me/drive não funciona para identidades de aplicação). Para enviar arquivos em chats/canais de grupo, o bot faz upload para um site do SharePoint e cria um link de compartilhamento.
Configuração
-
Adicionar permissões da Graph API no Entra ID (Azure AD) → App Registration:
Sites.ReadWrite.All(Application) - upload de arquivos no SharePointChat.Read.All(Application) - opcional, habilita links de compartilhamento por usuário
- Conceder consentimento de administrador para o tenant.
-
Obter o ID do site do SharePoint:
-
Configurar o OpenClaw:
Comportamento de compartilhamento
| Permissão | Comportamento de compartilhamento |
|---|---|
Sites.ReadWrite.All apenas | Link de compartilhamento para toda a organização |
Sites.ReadWrite.All + Chat.Read.All | Link de compartilhamento por usuário (apenas membros do chat) |
Chat.Read.All estiver ausente, o bot retorna ao compartilhamento para toda a organização.
Comportamento de fallback
| Cenário | Resultado |
|---|---|
Chat em grupo + arquivo + sharePointSiteId configurado | Upload no SharePoint, enviar link de compartilhamento |
Chat em grupo + arquivo + sem sharePointSiteId | Tentar upload no OneDrive (pode falhar), enviar apenas texto |
| Chat pessoal + arquivo | Fluxo FileConsentCard (funciona sem SharePoint) |
| Qualquer contexto + imagem | Inline codificado em Base64 (funciona sem SharePoint) |
Local de armazenamento dos arquivos
Os arquivos enviados são armazenados em uma pasta/OpenClawShared/ na biblioteca de documentos padrão do site do SharePoint configurado.
Enquetes (Adaptive Cards)
O OpenClaw envia enquetes do Teams como Adaptive Cards (não existe API nativa de enquetes do Teams).- CLI:
openclaw message poll --channel msteams --target conversation:<id> ... - Os votos são registrados pelo gateway em
~/.openclaw/msteams-polls.json. - O gateway deve permanecer online para registrar votos.
- As enquetes ainda não publicam automaticamente resumos de resultados (inspecione o arquivo de armazenamento, se necessário).
Adaptive Cards (arbitrários)
Envie qualquer JSON de Adaptive Card para usuários ou conversas do Teams usando a ferramentamessage ou a CLI.
O parâmetro card aceita um objeto JSON de Adaptive Card. Quando card é fornecido, o texto da mensagem é opcional.
Ferramenta do agente:
Formatos de destino
Os destinos do MSTeams usam prefixos para distinguir entre usuários e conversas:| Tipo de destino | Formato | Exemplo |
|---|---|---|
| Usuário (por ID) | user:<aad-object-id> | user:40a1a0ed-4ff2-4164-a219-55518990c197 |
| Usuário (por nome) | user:<display-name> | user:John Smith (requer Graph API) |
| Grupo/canal | conversation:<conversation-id> | conversation:19:[email protected] |
| Grupo/canal (raw) | <conversation-id> | 19:[email protected] (se contiver @thread) |
user:, nomes assumem resolução de grupo/equipe. Sempre use user: ao direcionar pessoas por nome de exibição.
Mensagens proativas
- Mensagens proativas só são possíveis após um usuário ter interagido, pois armazenamos referências de conversa nesse ponto.
- Veja
/gateway/configurationparadmPolicye restrições por lista de permissões.
IDs de equipe e canal (armadilha comum)
O parâmetro de consultagroupId nas URLs do Teams NÃO é o ID da equipe usado para configuração. Extraia os IDs do caminho da URL:
URL da equipe:
- ID da equipe = segmento do caminho após
/team/(decodificado da URL, ex.:19:[email protected]) - ID do canal = segmento do caminho após
/channel/(decodificado da URL) - Ignore o parâmetro de consulta
groupId
Canais privados
Bots têm suporte limitado em canais privados:| Funcionalidade | Canais padrão | Canais privados |
|---|---|---|
| Instalação do bot | Sim | Limitado |
| Mensagens em tempo real (webhook) | Sim | Pode não funcionar |
| Permissões RSC | Sim | Pode se comportar diferente |
| @menções | Sim | Se o bot for acessível |
| Histórico via Graph API | Sim | Sim (com permissões) |
- Use canais padrão para interações com o bot
- Use DMs — usuários sempre podem falar diretamente com o bot
- Use Graph API para acesso histórico (requer
ChannelMessage.Read.All)
Problemas comuns
Problemas comuns
- Imagens não aparecem em canais: permissões do Graph ou consentimento admin ausentes. Reinstale o app do Teams e feche/reabra completamente o Teams.
- Sem respostas no canal: menções são exigidas por padrão; defina
channels.msteams.requireMention=falseou configure por equipe/canal. - Incompatibilidade de versão (Teams ainda mostra manifesto antigo): remova e readicione o app e feche completamente o Teams para atualizar.
- 401 Unauthorized do webhook: esperado ao testar manualmente sem JWT do Azure — indica que o endpoint é alcançável, mas a autenticação falhou. Use o Azure Web Chat para testar corretamente.
Erros ao enviar o manifesto
- “Icon file cannot be empty”: o manifesto referencia arquivos de ícone com 0 bytes. Crie ícones PNG válidos (32x32 para
outline.png, 192x192 paracolor.png). - “webApplicationInfo.Id already in use”: o app ainda está instalado em outra equipe/chat. Encontre e desinstale primeiro ou aguarde 5–10 minutos para propagação.
- “Something went wrong” no upload: envie via https://admin.teams.microsoft.com, abra as DevTools do navegador (F12) → aba Network e verifique o corpo da resposta para o erro real.
- Falha no sideload: tente “Upload an app to your org’s app catalog” em vez de “Upload a custom app” — isso geralmente contorna restrições de sideload.
Permissões RSC não funcionando
- Verifique se
webApplicationInfo.idcorresponde exatamente ao App ID do seu bot - Reenvie o app e reinstale na equipe/chat
- Verifique se o administrador da organização bloqueou permissões RSC
- Confirme que você está usando o escopo correto:
ChannelMessage.Read.Grouppara equipes,ChatMessage.Read.Chatpara chats em grupo
Referências
- Create Azure Bot - guia de configuração do Azure Bot
- Teams Developer Portal - criar/gerenciar apps do Teams
- Esquema do manifesto do app do Teams
- Receber mensagens de canal com RSC
- Referência de permissões RSC
- Manipulação de arquivos por bots do Teams (canal/grupo requer Graph)
- Mensagens proativas