Microsoft Teams
État : le texte + les pièces jointes en DM sont pris en charge ; l’envoi de fichiers vers les channels/groupes nécessite sharePointSiteId + des autorisations Graph (voir Sending files in group chats). Les sondages sont envoyés via Adaptive Cards. Les actions de message exposent un upload-file explicite pour les envois priorisant le fichier.
Plugin inclus
Section intitulée « Plugin inclus »Microsoft Teams est fourni en tant que plugin inclus dans les versions actuelles d’OpenClaw, donc aucune installation séparée n’est requise dans la version empaquetée normale.
Si vous utilisez une ancienne version ou une installation personnalisée qui exclut Teams intégré, installez directement le package npm :
openclaw plugins install @openclaw/msteamsUtilisez le package nu pour suivre l’étiquette de publication officielle actuelle. Épinglez une version exacte uniquement lorsque vous avez besoin d’une installation reproductible.
Extraction locale (lors de l’exécution depuis un dépôt git) :
openclaw plugins install ./path/to/local/msteams-pluginDétails : Plugins
Installation rapide
Section intitulée « Installation rapide »Le @microsoft/teams.cli gère l’inscription du bot, la création du manifeste et la génération des identifiants en une seule commande.
1. Installer et se connecter
npm install -g @microsoft/teams.cli@previewteams loginteams status # verify you're logged in and see your tenant info2. Démarrer un tunnel (Teams ne peut pas atteindre localhost)
Installez et authentifiez le CLI devtunnel si ce n’est pas déjà fait (getting started guide).
# One-time setup (persistent URL across sessions):devtunnel create my-openclaw-bot --allow-anonymousdevtunnel port create my-openclaw-bot -p 3978 --protocol auto
# Each dev session:devtunnel host my-openclaw-bot# Your endpoint: https://<tunnel-id>.devtunnels.ms/api/messagesAlternatives : ngrok http 3978 ou tailscale funnel 3978 (mais ceux-ci peuvent changer les URL à chaque session).
3. Créer l’application
teams app create \ --name "OpenClaw" \ --endpoint "https://<your-tunnel-url>/api/messages"Cette commande unique :
- Crée une application Entra ID (Azure AD)
- Génère une clé secrète client
- Crée et télécharge un manifeste d’application Teams (avec des icônes)
- Inscrit le bot (géré par Teams par défaut - aucun abonnement Azure requis)
La sortie affichera CLIENT_ID, CLIENT_SECRET, TENANT_ID et un ID d’application Teams - notez-les pour les étapes suivantes. Il propose également d’installer l’application directement dans Teams.
4. Configurez OpenClaw à l’aide des informations d’identification de la sortie :
{ channels: { msteams: { enabled: true, appId: "<CLIENT_ID>", appPassword: "<CLIENT_SECRET>", tenantId: "<TENANT_ID>", webhook: { port: 3978, path: "/api/messages" }, }, },}Ou utilisez directement les variables d’environnement : MSTEAMS_APP_ID, MSTEAMS_APP_PASSWORD, MSTEAMS_TENANT_ID.
5. Installez l’application dans Teams
teams app create vous invitera à installer l’application - sélectionnez « Installer dans Teams ». Si vous avez ignoré cette étape, vous pouvez obtenir le lien plus tard :
teams app get <teamsAppId> --install-link6. Vérifiez que tout fonctionne
teams app doctor <teamsAppId>Cela exécute des diagnostics sur l’enregistrement du bot, la configuration de l’application AAD, la validité du manifeste et la configuration SSO.
Pour les déploiements en production, envisagez d’utiliser la federated authentication (certificat ou identité gérée) au lieu des secrets client.
Objectifs
Section intitulée « Objectifs »- Parler à OpenClaw via Teams DM, conversations de groupe ou channels.
- Garder le routage déterministe : les réponses vont toujours au channel d’où elles proviennent.
- Par défaut, comportement de channel sécurisé (mentions requises sauf configuration contraire).
Écritures de configuration
Section intitulée « Écritures de configuration »Par défaut, Microsoft Teams est autorisé à écrire des mises à jour de configuration déclenchées par /config set|unset (nécessite commands.config: true).
Désactiver avec :
{ channels: { msteams: { configWrites: false } },}Contrôle d’accès (DMs + groupes)
Section intitulée « Contrôle d’accès (DMs + groupes) »Accès DM
- Par défaut :
channels.msteams.dmPolicy = "pairing". Les expéditeurs inconnus sont ignorés jusqu’à approbation. channels.msteams.allowFromdoit utiliser des ID d’objet AAD stables ou des groupes d’accès d’expéditeur statiques tels queaccessGroup:core-team.- Ne vous fiez pas à la correspondance UPN/nom d’affichage pour les listes blanches - ils peuvent changer. OpenClaw désactive la correspondance directe des noms par défaut ; activez-la explicitement avec
channels.msteams.dangerouslyAllowNameMatching: true. - L’assistant peut résoudre les noms en ID via Microsoft Graph lorsque les informations d’identification le permettent.
Accès de groupe
- Par défaut :
channels.msteams.groupPolicy = "allowlist"(bloqué sauf si vous ajoutezgroupAllowFrom). Utilisezchannels.defaults.groupPolicypour remplacer la valeur par défaut lorsqu’elle n’est pas définie. channels.msteams.groupAllowFromcontrôle quels expéditeurs ou groupes d’accès d’expéditeur statiques peuvent déclencher dans les conversations de groupe/canaux (revient àchannels.msteams.allowFrom).- Définissez
groupPolicy: "open"pour autoriser n’importe quel membre (toujours restreint aux mentions par défaut). - Pour n’autoriser aucun channel, définissez
channels.msteams.groupPolicy: "disabled".
Exemple :
{ channels: { msteams: { groupPolicy: "allowlist", groupAllowFrom: ["00000000-0000-0000-0000-000000000000", "accessGroup:core-team"], }, },}Teams + liste d’autorisation de channels
- Délimitez les réponses de groupe/channel en listant les équipes et les channels sous
channels.msteams.teams. - Les clés doivent utiliser les ID de conversation Teams stables provenant des liens Teams, et non les noms d’affichage modifiables.
- Lorsque
groupPolicy="allowlist"et une liste d’autorisation d’équipes sont présents, seules les équipes/channels listés sont acceptés (restreint aux mentions). - L’assistant de configuration accepte les entrées
Team/Channelet les stocke pour vous. - Au démarrage, OpenClaw résout les noms des listes d’autorisation d’équipe/channel et d’utilisateur en ID (lorsque les autorisations Graph le permettent)
et enregistre le mappage ; les noms d’équipe/channel non résolus sont conservés tels quels mais ignorés pour le routage par défaut, sauf si
channels.msteams.dangerouslyAllowNameMatching: trueest activé.
Exemple :
{ channels: { msteams: { groupPolicy: "allowlist", teams: { "My Team": { channels: { General: { requireMention: true }, }, }, }, }, },}Configuration manuelle (sans le Teams CLI)
Si vous ne pouvez pas utiliser le Teams CLI, vous pouvez configurer le bot manuellement via le portail Azure.
Fonctionnement
Section intitulée « Fonctionnement »- Assurez-vous que le plugin Microsoft Teams est disponible (inclus dans les versions actuelles).
- Créez un Azure Bot (ID d’application + secret + ID de locataire).
- Créez un package d’application Teams qui référence le bot et inclut les autorisations RSC ci-dessous.
- Téléchargez/installez l’application Teams dans une équipe (ou l’étendue personnelle pour les DMs).
- Configurez
msteamsdans~/.openclaw/openclaw.json(ou les env vars) et démarrez la passerelle. - Par défaut, la passerelle écoute le trafic du webhook Bot Framework sur
/api/messages.
Étape 1 : Créer un Azure Bot
Section intitulée « Étape 1 : Créer un Azure Bot »-
Accédez à Create Azure Bot
-
Remplissez l’onglet Basics :
Champ Valeur Nom du bot Le nom de votre bot, p. ex. openclaw-msteams(doit être unique)Abonnement Sélectionnez votre abonnement Azure Groupe de ressources Créer un nouveau ou utiliser un existant Niveau tarifaire Gratuit pour le développement/les tests Type d’application Monolocataire (recommandé - voir la note ci-dessous) Type de création Créer un nouvel ID d’application Microsoft
- Cliquez sur Vérifier + créer → Créer (attendre ~1-2 minutes)
Étape 2 : Obtenir les informations d’identification
Section intitulée « Étape 2 : Obtenir les informations d’identification »- Accédez à votre ressource Azure Bot → Configuration
- Copiez l’ID d’application Microsoft → il s’agit de votre
appId - Cliquez sur Gérer le mot de passe → accédez à l’inscription de l’application
- Sous Certificats et secrets → Nouveau secret client → copiez la Valeur → il s’agit de votre
appPassword - Allez dans Vue d’ensemble → copiez ID de répertoire (locataire) → c’est votre
tenantId
Étape 3 : Configurer le point de terminaison de messagerie
Section intitulée « Étape 3 : Configurer le point de terminaison de messagerie »- Dans Azure Bot → Configuration
- Définissez le Point de terminaison de messagerie sur votre URL de webhook :
- Production :
https://your-domain.com/api/messages - Dev local : Utilisez un tunnel (voir Local Development ci-dessous)
- Production :
Étape 4 : Activer le canal Teams
Section intitulée « Étape 4 : Activer le canal Teams »- Dans Azure Bot → Canaux
- Cliquez sur Microsoft Teams → Configurer → Enregistrer
- Acceptez les conditions d’utilisation
Étape 5 : Créer le manifeste de l’application Teams
Section intitulée « Étape 5 : Créer le manifeste de l’application Teams »- Incluez une entrée
botavecbotId = <App ID>. - Étendues (scopes) :
personal,team,groupChat. supportsFiles: true(requis pour la gestion des fichiers dans l’étendue personnelle).- Ajoutez les autorisations RSC (voir RSC Permissions).
- Créez les icônes :
outline.png(32x32) etcolor.png(192x192). - Compressez les trois fichiers ensemble :
manifest.json,outline.png,color.png.
Étape 6 : Configurer OpenClaw
Section intitulée « Étape 6 : Configurer OpenClaw »{ channels: { msteams: { enabled: true, appId: "<APP_ID>", appPassword: "<APP_PASSWORD>", tenantId: "<TENANT_ID>", webhook: { port: 3978, path: "/api/messages" }, }, },}Variables d’environnement : MSTEAMS_APP_ID, MSTEAMS_APP_PASSWORD, MSTEAMS_TENANT_ID.
Étape 7 : Exécuter le Gateway
Section intitulée « Étape 7 : Exécuter le Gateway »Le channel Teams démarre automatiquement lorsque le plugin est disponible et que la configuration msteams existe avec les identifiants.
Authentification fédérée (certificat et identité gérée)
Section intitulée « Authentification fédérée (certificat et identité gérée) »Ajouté dans la version 2026.4.11
Pour les déploiements en production, OpenClaw prend en charge l’authentification fédérée comme alternative plus sécurisée aux secrets clients. Deux méthodes sont disponibles :
Option A : Authentification basée sur un certificat
Section intitulée « Option A : Authentification basée sur un certificat »Utilisez un certificat PEM enregistré avec votre inscription d’application Entra ID.
Configuration :
- Générez ou obtenez un certificat (format PEM avec clé privée).
- Dans Entra ID → Inscription d’application → Certificats et secrets → Certificats → Télécharger le certificat public.
Config :
{ channels: { msteams: { enabled: true, appId: "<APP_ID>", tenantId: "<TENANT_ID>", authType: "federated", certificatePath: "/path/to/cert.pem", webhook: { port: 3978, path: "/api/messages" }, }, },}Variables d’environnement :
MSTEAMS_AUTH_TYPE=federatedMSTEAMS_CERTIFICATE_PATH=/path/to/cert.pem
Option B : Identité gérée Azure
Section intitulée « Option B : Identité gérée Azure »Utilisez l’identité gérée Azure pour une authentification sans mot de passe. C’est idéal pour les déploiements sur l’infrastructure Azure (AKS, App Service, machines virtuelles Azure) où une identité gérée est disponible.
Fonctionnement :
- Le pod/VM du bot possède une identité gérée (attribuée par le système ou par l’utilisateur).
- Une information d’identification d’identité fédérée lie l’identité gérée à l’inscription d’application Entra ID.
- Lors de l’exécution, OpenClaw utilise OpenClaw
@azure/identitypour acquérir des jetons à partir du point de terminaison IMDS Azure (169.254.169.254). - Le jeton est transmis au SDK Teams pour l’authentification du bot.
Prérequis :
- Infrastructure Azure avec l’identité gérée activée (identité de charge de travail AKS, App Service, machine virtuelle)
- Informations d’identification d’identité fédérée créées sur l’inscription de l’application Entra ID
- Accès réseau à IMDS (
169.254.169.254:80) depuis le pod/la machine virtuelle
Configuration (identité gérée attribuée par le système) :
{ channels: { msteams: { enabled: true, appId: "<APP_ID>", tenantId: "<TENANT_ID>", authType: "federated", useManagedIdentity: true, webhook: { port: 3978, path: "/api/messages" }, }, },}Configuration (identité gérée attribuée par l’utilisateur) :
{ channels: { msteams: { enabled: true, appId: "<APP_ID>", tenantId: "<TENANT_ID>", authType: "federated", useManagedIdentity: true, managedIdentityClientId: "<MI_CLIENT_ID>", webhook: { port: 3978, path: "/api/messages" }, }, },}Variables d’environnement :
MSTEAMS_AUTH_TYPE=federatedMSTEAMS_USE_MANAGED_IDENTITY=trueMSTEAMS_MANAGED_IDENTITY_CLIENT_ID=<client-id>(uniquement pour l’identité attribuée par l’utilisateur)
Configuration de l’identité de charge de travail AKS
Section intitulée « Configuration de l’identité de charge de travail AKS »Pour les déploiements AKS utilisant l’identité de charge de travail :
-
Activez l’identité de charge de travail sur votre cluster AKS.
-
Créez des informations d’identification d’identité fédérée sur l’inscription de l’application Entra ID :
Fenêtre de terminal az ad app federated-credential create --id <APP_OBJECT_ID> --parameters '{"name": "my-bot-workload-identity","issuer": "<AKS_OIDC_ISSUER_URL>","subject": "system:serviceaccount:<NAMESPACE>:<SERVICE_ACCOUNT>","audiences": ["api://AzureADTokenExchange"]}' -
Annotez le compte de service Kubernetes avec l’ID client de l’application :
apiVersion: v1kind: ServiceAccountmetadata:name: my-bot-saannotations:azure.workload.identity/client-id: "<APP_CLIENT_ID>" -
Étiquetez le pod pour l’injection de l’identité de charge de travail :
metadata:labels:azure.workload.identity/use: "true" -
Assurez l’accès réseau à IMDS (
169.254.169.254) - si vous utilisez NetworkPolicy, ajoutez une règle de sortie autorisant le trafic vers169.254.169.254/32sur le port 80.
Comparaison des types d’authentification
Section intitulée « Comparaison des types d’authentification »| Méthode | Configuration | Avantages | Inconvénients |
|---|---|---|---|
| Secret client | appPassword | Configuration simple | Rotation du secret requise, moins sécurisé |
| Certificat | authType: "federated" + certificatePath | Aucun secret partagé sur le réseau | Surcharge de gestion des certificats |
| Identité gérée | authType: "federated" + useManagedIdentity | Sans mot de passe, aucun secret à gérer | Infrastructure Azure requise |
Comportement par défaut : Lorsque authType n’est pas défini, OpenClaw utilise par défaut l’authentification par secret client. Les configurations existantes continuent de fonctionner sans modification.
Développement local (tunneling)
Section intitulée « Développement local (tunneling) »Teams ne peut pas atteindre localhost. Utilisez un tunnel de développement persistant afin que votre URL reste la même d’une session à l’autre :
# One-time setup:devtunnel create my-openclaw-bot --allow-anonymousdevtunnel port create my-openclaw-bot -p 3978 --protocol auto
# Each dev session:devtunnel host my-openclaw-botAlternatives : ngrok http 3978 ou tailscale funnel 3978 (les URL peuvent changer à chaque session).
Si l’URL de votre tunnel change, mettez à jour le point de terminaison :
teams app update <teamsAppId> --endpoint "https://<new-url>/api/messages"Tester le Bot
Section intitulée « Tester le Bot »Exécuter les diagnostics :
teams app doctor <teamsAppId>Vérifie l’inscription du bot, l’application AAD, le manifeste et la configuration SSO en une seule passe.
Envoyer un message de test :
- Installer l’application Teams (utilisez le lien d’installation provenant de
teams app get <id> --install-link) - Trouver le bot dans Teams et envoyer un DM
- Vérifier les journaux de la passerelle pour l’activité entrante
Variables d’environnement
Section intitulée « Variables d’environnement »Toutes les clés de configuration peuvent être définies via des variables d’environnement à la place :
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_IDMSTEAMS_AUTH_TYPE(optionnel :"secret"ou"federated")MSTEAMS_CERTIFICATE_PATH(fédéré + certificat)MSTEAMS_CERTIFICATE_THUMBPRINT(optionnel, non requis pour l’auth)MSTEAMS_USE_MANAGED_IDENTITY(fédéré + identité gérée)MSTEAMS_MANAGED_IDENTITY_CLIENT_ID(identité gérée affectée par l’utilisateur uniquement)
Action Info membre
Section intitulée « Action Info membre »OpenClaw expose une action member-info basée sur Graph pour Microsoft Teams afin que les agents et automatisations puissent récupérer les détails des membres du channel (nom d’affichage, e-mail, rôle) directement à partir de Microsoft Graph.
Conditions requises :
- Autorisation RSC
Member.Read.Group(déjà présente dans le manifeste recommandé) - Pour les recherches inter-équipes :
User.Read.AllGraph Application permission avec consentement administrateur
L’action est contrôlée par channels.msteams.actions.memberInfo (par défaut : activé lorsque les identifiants Graph sont disponibles).
Contexte de l’historique
Section intitulée « Contexte de l’historique »channels.msteams.historyLimitcontrôle le nombre de messages récents de canal/groupe inclus dans l’invite.- Revient à
messages.groupChat.historyLimit. Définissez0pour désactiver (par défaut 50). - L’historique des fils de discussion récupéré est filtré par les listes autorisées d’expéditeurs (
allowFrom/groupAllowFrom), de sorte que l’amorçage du contexte du fil inclut uniquement les messages des expéditeurs autorisés. - Le contexte des pièces jointes citées (
ReplyTo*dérivé du HTML de réponse Teams) est actuellement transmis tel quel. - En d’autres termes, les listes d’autorisation contrôlent qui peut déclencher l’agent ; seuls certains chemins de contexte supplémentaires sont filtrés aujourd’hui.
- L’historique des DM peut être limité avec
channels.msteams.dmHistoryLimit(tours utilisateur). Remplacements par utilisateur :channels.msteams.dms["<user_id>"].historyLimit.
Autorisations RSC Teams actuelles (manifeste)
Section intitulée « Autorisations RSC Teams actuelles (manifeste) »Ce sont les autorisations resourceSpecific existantes dans le manifeste de notre application Teams. Elles ne s’appliquent qu’à l’intérieur de l’équipe/discussion où l’application est installée.
Pour les canaux (étendue équipe) :
ChannelMessage.Read.Group(Application) - recevoir tous les messages de canal sans @mentionChannelMessage.Send.Group(Application)Member.Read.Group(Application)Owner.Read.Group(Application)ChannelSettings.Read.Group(Application)TeamMember.Read.Group(Application)TeamSettings.Read.Group(Application)
Pour les discussions de groupe :
ChatMessage.Read.Chat(Application) - recevoir tous les messages de chat de groupe sans @mention
Pour ajouter des autorisations RSC via le Teams CLI :
teams app rsc add <teamsAppId> ChannelMessage.Read.Group --type ApplicationExemple de manifeste Teams (expurgé)
Section intitulée « Exemple de manifeste Teams (expurgé) »Exemple minimal et valide avec les champs obligatoires. Remplacez les ID et les URL.
{ $schema: "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json", manifestVersion: "1.23", version: "1.0.0", id: "00000000-0000-0000-0000-000000000000", name: { short: "OpenClaw" }, developer: { name: "Your Org", websiteUrl: "https://example.com", privacyUrl: "https://example.com/privacy", termsOfUseUrl: "https://example.com/terms", }, description: { short: "OpenClaw in Teams", full: "OpenClaw in Teams" }, icons: { outline: "outline.png", color: "color.png" }, accentColor: "#5B6DEF", bots: [ { botId: "11111111-1111-1111-1111-111111111111", scopes: ["personal", "team", "groupChat"], isNotificationOnly: false, supportsCalling: false, supportsVideo: false, supportsFiles: true, }, ], webApplicationInfo: { id: "11111111-1111-1111-1111-111111111111", }, authorization: { permissions: { resourceSpecific: [ { name: "ChannelMessage.Read.Group", type: "Application" }, { name: "ChannelMessage.Send.Group", type: "Application" }, { name: "Member.Read.Group", type: "Application" }, { name: "Owner.Read.Group", type: "Application" }, { name: "ChannelSettings.Read.Group", type: "Application" }, { name: "TeamMember.Read.Group", type: "Application" }, { name: "TeamSettings.Read.Group", type: "Application" }, { name: "ChatMessage.Read.Chat", type: "Application" }, ], }, },}Mises en garde du manifeste (champs obligatoires)
Section intitulée « Mises en garde du manifeste (champs obligatoires) »bots[].botIddoit correspondre à l’ID de l’application Azure Bot.webApplicationInfo.iddoit correspondre à l’ID de l’application Azure Bot.bots[].scopesdoit inclure les surfaces que vous prévoyez d’utiliser (personal,team,groupChat).bots[].supportsFiles: trueest requis pour la gestion des fichiers dans l’étendue personnelle.authorization.permissions.resourceSpecificdoit inclure la lecture/l’envoi dans le channel si vous voulez le trafic de channel.
Mise à jour d’une application existante
Section intitulée « Mise à jour d’une application existante »Pour mettre à jour une application Teams déjà installée (par exemple, pour ajouter des autorisations RSC) :
# Download, edit, and re-upload the manifestteams app manifest download <teamsAppId> manifest.json# Edit manifest.json locally...teams app manifest upload manifest.json <teamsAppId># Version is auto-bumped if content changedAprès la mise à jour, réinstallez l’application dans chaque équipe pour que les nouvelles autorisations prennent effet, et quittez et relancez complètement Teams (et ne fermez pas simplement la fenêtre) pour effacer les métadonnées de l’application en cache.
Mise à jour manuelle du manifeste (sans CLI)
- Mettez à jour votre
manifest.jsonavec les nouveaux paramètres - Incrémentez le champ
version(par exemple,1.0.0→1.1.0) - Recompressez le manifeste avec les icônes (
manifest.json,outline.png,color.png) - Téléchargez le nouveau fichier zip :
- Centre d’administration Teams : Applications Teams → Gérer les applications → trouver votre application → Télécharger une nouvelle version
- Chargement latéral : Dans Teams → Applications → Gérer vos applications → Charger une application personnalisée
Capacités : RSC uniquement vs Graph
Section intitulée « Capacités : RSC uniquement vs Graph »Avec uniquement Teams RSC (application installée, aucune permission d’API API)
Section intitulée « Avec uniquement Teams RSC (application installée, aucune permission d’API API) »Fonctionne :
- Lire le texte des messages de channel.
- Envoyer le texte des messages de channel.
- Recevoir des pièces jointes personnelles (DM).
NE fonctionne PAS :
- Contenu des images ou fichiers de channel/groupe (la charge utile ne comprend qu’une partie HTML).
- Télécharger les pièces jointes stockées dans SharePoint/OneDrive.
- Lire l’historique des messages (au-delà de l’événement webhook en direct).
Avec Teams RSC + Microsoft Graph (permissions d’Application)
Section intitulée « Avec Teams RSC + Microsoft Graph (permissions d’Application) »Ajoute :
- Télécharger le contenu hébergé (images collées dans les messages).
- Télécharger les pièces jointes de fichiers stockées dans SharePoint/OneDrive.
- Lire l’historique des messages de channel/chat via Graph.
RSC vs API API
Section intitulée « RSC vs API API »| Capacité | Permissions RSC | API API |
|---|---|---|
| Messages en temps réel | Oui (via webhook) | Non (sondage uniquement) |
| Messages historiques | Non | Oui (peut interroger l’historique) |
| Complexité de la configuration | Manifeste d’application uniquement | Nécessite le consentement de l’administrateur + flux de jeton |
| Fonctionne hors ligne | Non (doit être en cours d’exécution) | Oui (interrogation à tout moment) |
En résumé : RSC est pour l’écoute en temps réel ; Graph API est pour l’accès historique. Pour rattraper les messages manqués hors ligne, vous avez besoin de Graph API avec ChannelMessage.Read.All (nécessite le consentement de l’administrateur).
Média et historique activés par Graph (requis pour les channels)
Section intitulée « Média et historique activés par Graph (requis pour les channels) »Si vous avez besoin d’images/fichiers dans les channels ou souhaitez récupérer l’historique des messages, vous devez activer les autorisations Microsoft Graph et accorder le consentement de l’administrateur.
- Dans Entra ID (Azure AD) Inscription d’application, ajoutez les autorisations d’application Microsoft Graph :
ChannelMessage.Read.All(pièces jointes de channel + historique)Chat.Read.AllouChatMessage.Read.All(discussions de groupe)
- Accorder le consentement administrateur pour le client.
- Augmentez la version du manifeste de l’application Teams, téléchargez-la à nouveau et réinstallez l’application dans Teams.
- Quittez entièrement et relancez Teams pour effacer les métadonnées de l’application en cache.
Autorisation supplémentaire pour les mentions d’utilisateur : Les @mentions d’utilisateur fonctionnent immédiatement pour les utilisateurs de la conversation. Cependant, si vous souhaitez rechercher dynamiquement et mentionner des utilisateurs qui ne sont pas dans la conversation actuelle, ajoutez l’autorisation User.Read.All (Application) et accordez le consentement administrateur.
Limitations connues
Section intitulée « Limitations connues »Délais d’expiration des webhooks
Section intitulée « Délais d’expiration des webhooks »Teams livre les messages via un webhook HTTP. Si le traitement prend trop de temps (par exemple, des réponses LLM lentes), vous pouvez voir :
- Délais d’expiration de la Gateway
- Teams qui réessaie d’envoyer le message (provoquant des doublons)
- Réponses ignorées
OpenClaw gère cela en répondant rapidement et en envoyant des réponses de manière proactive, mais des réponses très lentes peuvent toujours causer des problèmes.
Formatage
Section intitulée « Formatage »Le markdown Teams est plus limité que Slack ou Discord :
- Le formatage de base fonctionne : gras, italique,
code, liens - Le markdown complexe (tableaux, listes imbriquées) peut ne pas s’afficher correctement
- Les cartes adaptatives (Adaptive Cards) sont prises en charge pour les sondages et les envois de présentation sémantique (voir ci-dessous)
Configuration
Section intitulée « Configuration »Paramètres clés (voir /gateway/configuration pour les modèles de canal partagés) :
channels.msteams.enabled: activer/désactiver le channel.channels.msteams.appId,channels.msteams.appPassword,channels.msteams.tenantId: identifiants du bot.channels.msteams.webhook.port(par défaut3978)channels.msteams.webhook.path(par défaut/api/messages)channels.msteams.dmPolicy:pairing | allowlist | open | disabled(par défaut : appairage)channels.msteams.allowFrom: liste d’autorisation de DM (IDs d’objets AAD recommandés). L’assistant résout les noms en IDs lors de la configuration lorsque l’accès Graph est disponible.channels.msteams.dangerouslyAllowNameMatching: interrupteur de secours pour réactiver la correspondance mutable UPN/nom d’affichage et le routage direct par nom d’équipe/channel.channels.msteams.textChunkLimit: taille du bloc de texte sortant.channels.msteams.chunkMode:length(par défaut) ounewlinepour diviser sur les lignes vides (limites de paragraphe) avant le découpage par longueur.channels.msteams.mediaAllowHosts: liste d’autorisation pour les hôtes de pièces jointes entrantes (par défaut les domaines Microsoft/Teams).channels.msteams.mediaAuthAllowHosts: liste d’autorisation pour joindre les en-têtes d’autorisation lors des nouvelles tentatives de média (par défaut : hôtes Graph + Bot Framework).channels.msteams.requireMention: exiger une @mention dans les canaux/groupes (vrai par défaut).channels.msteams.replyStyle:thread | top-level(voir Reply Style).channels.msteams.teams.<teamId>.replyStyle: substitution par équipe.channels.msteams.teams.<teamId>.requireMention: substitution par équipe.channels.msteams.teams.<teamId>.tools: substitutions de stratégie de tool par équipe par défaut (allow/deny/alsoAllow) utilisées lorsqu’une substitution de canal est manquante.channels.msteams.teams.<teamId>.toolsBySender: substitutions de stratégie de tool par équipe par expéditeur par défaut (caractère générique"*"pris en charge).channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: remplacement par channel.channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: remplacement par channel.channels.msteams.teams.<teamId>.channels.<conversationId>.tools: remplacements de la stratégie de tool par channel (allow/deny/alsoAllow).channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: remplacements de la stratégie de tool par channel et par expéditeur (le caractère générique"*"est pris en charge).- Les clés
toolsBySenderdoivent utiliser des préfixes explicites :channel:,id:,e164:,username:,name:(les clés héritées sans préfixe mappent toujours uniquement versid:). channels.msteams.actions.memberInfo: activer ou désactiver l’action d’informations sur les membres basée sur Graph (par défaut : activé lorsque les identifiants Graph sont disponibles).channels.msteams.authType: type d’authentification -"secret"(par défaut) ou"federated".channels.msteams.certificatePath: chemin vers le fichier de certificat PEM (authentification fédérée + certificat).channels.msteams.certificateThumbprint: empreinte du certificat (facultatif, non requis pour l’authentification).channels.msteams.useManagedIdentity: activer l’authentification par identité gérée (mode fédéré).channels.msteams.managedIdentityClientId: ID client pour l’identité gérée affectée par l’utilisateur.channels.msteams.sharePointSiteId: ID du site SharePoint pour l’envoi de fichiers dans les conversations de groupe/canaux (voir Envoi de fichiers dans les conversations de groupe).
Routage et sessions
Section intitulée « Routage et sessions »- Les clés de session suivent le format standard de l’agent (voir /concepts/session) :
- Les messages directs partagent la session principale (
agent:<agentId>:<mainKey>). - Channel/group messages use conversation id:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- Les messages directs partagent la session principale (
Reply style: threads vs posts
Section intitulée « Reply style: threads vs posts »Teams recently introduced two channel UI styles over the same underlying data model:
| Style | Description | Recommandé replyStyle |
|---|---|---|
| Posts (classic) | Messages appear as cards with threaded replies underneath | thread (par défaut) |
| Threads (Slack-like) | Messages flow linearly, more like Slack | top-level |
Le problème : L’API Teams n’expose pas le style d’interface utilisateur utilisé par un channel. Si vous utilisez le mauvais replyStyle :
threaddans un channel de style Threads → les réponses apparaissent de manière maladroite et imbriquéestop-leveldans un channel de style Posts → les réponses apparaissent comme des publications de niveau supérieur distinctes au lieu d’être dans le fil de discussion
Solution : Configurez replyStyle par channel en fonction de la configuration du channel :
{ channels: { msteams: { replyStyle: "thread", teams: { channels: { replyStyle: "top-level", }, }, }, }, }, },}Priorité de résolution
Section intitulée « Priorité de résolution »Lorsque le bot envoie une réponse dans un channel, replyStyle est résolu à partir de la substitution la plus spécifique jusqu’à la valeur par défaut. La première valeur non undefined l’emporte :
- Par channel —
channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle - Par équipe —
channels.msteams.teams.<teamId>.replyStyle - Global —
channels.msteams.replyStyle - Par défaut implicite — dérivé de
requireMention:requireMention: true→threadrequireMention: false→top-level
Si vous définissez requireMention: false globalement sans replyStyle explicite, les mentions dans les channels de style Posts apparaîtront comme des publications de niveau supérieur même lorsque le message entrant était une réponse dans un fil. Épinglez replyStyle: "thread" au niveau global, de l’équipe ou du channel pour éviter les surprises.
Préservation du contexte du fil
Section intitulée « Préservation du contexte du fil »Lorsque replyStyle: "thread"OpenClaw est en vigueur et que le bot a été mentionné depuis un fil de discussion de channel, OpenClaw rattache la racine du fil d’origine à la référence de conversation sortante (19:…@thread.tacv2;messageid=<root>) afin que la réponse soit publiée dans le même fil. Cela s’applique aux envois en direct (dans le tour) et aux envois proactifs effectués après l’expiration du contexte de tour du Bot Framework (par exemple, agents de longue durée, réponses d’appels d’outil mises en file d’attente via mcp__openclaw__message).
La racine du fil est tirée du threadId stocké sur la référence de conversation. Les références stockées plus anciennes qui datent d’avant threadId reviennent à activityId (toute activité entrante ayant dernier amorcé la conversation), de sorte que les déploiements existants continuent de fonctionner sans réamorçage.
Lorsque replyStyle: "top-level" est en vigueur, les entrées de fil de channel sont intentionnellement répondues par de nouveaux messages de premier niveau — aucun suffixe de fil n’est attaché. Il s’agit du comportement correct pour les channels de style Threads ; si vous voyez des messages de premier niveau là où vous attendiez des réponses en fil, votre replyStyle est défini incorrectement pour ce channel.
Pièces jointes et images
Section intitulée « Pièces jointes et images »Limitations actuelles :
- DMs : Les images et les pièces jointes fonctionnent via les API de fichiers de bot Teams.
- Canaux/groupes : Les pièces jointes résident dans le stockage M365 (SharePoint/OneDrive). La charge utile du webhook n’inclut qu’un texte HTML, et non les octets réels du fichier. Les autorisations de l’API Graph sont requises pour télécharger les pièces jointes des canaux.
- Pour les envois explicites de type fichier en premier, utilisez
action=upload-fileavecmedia/filePath/path; lemessagefacultatif devient le texte/commentaire d’accompagnement, etfilenameremplace le nom téléchargé.
Sans les autorisations Graph, les messages de channel contenant des images seront reçus sous forme de texte uniquement (le contenu de l’image n’est pas accessible au bot).
Par défaut, OpenClaw ne télécharge les médias qu’à partir des noms d’hôte Microsoft/Teams. Remplacez par OpenClawchannels.msteams.mediaAllowHosts (utilisez ["*"] pour autoriser n’importe quel hôte).
Les en-têtes d’autorisation ne sont attachés que pour les hôtes de channels.msteams.mediaAuthAllowHosts (par défaut hôtes Graph + Bot Framework). Gardez cette liste stricte (évitez les suffixes multi-locataires).
Envoyer des fichiers dans les conversations de groupe
Section intitulée « Envoyer des fichiers dans les conversations de groupe »Les bots peuvent envoyer des fichiers dans les DMs en utilisant le flux FileConsentCard (intégré). Cependant, l’envoi de fichiers dans les conversations de groupe/canaux nécessite une configuration supplémentaire :
| Contexte | Comment les fichiers sont envoyés | Configuration nécessaire |
|---|---|---|
| DMs | FileConsentCard → l’utilisateur accepte → le bot télécharge | Fonctionne hors de la boîte |
| Conversations de groupe/canaux | Télécharger vers SharePoint → partager le lien | Nécessite sharePointSiteId + autorisations Graph |
| Images (tout contexte) | Codé en base64 en ligne | Fonctionne immédiatement |
Pourquoi les discussions de groupe ont besoin de SharePoint
Section intitulée « Pourquoi les discussions de groupe ont besoin de SharePoint »Les bots n’ont pas de lecteur OneDrive personnel (le point de terminaison de l’API /me/driveAPI Graph ne fonctionne pas pour les identités d’application). Pour envoyer des fichiers dans des conversations de groupe/canaux, le bot télécharge sur un site SharePoint et crée un lien de partage.
Configuration
Section intitulée « Configuration »-
Ajoutez des autorisations API Graph dans Entra ID (Azure AD) → Inscription de l’application :
Sites.ReadWrite.All(Application) - télécharger les fichiers sur SharePointChat.Read.All(Application) - facultatif, active les liens de partage par utilisateur
-
Accorder le consentement administrateur pour le locataire.
-
Obtenez l’ID de votre site SharePoint :
Fenêtre de terminal # Via Graph Explorer or curl with a valid token:curl -H "Authorization: Bearer $TOKEN" \"https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}"# Example: for a site at "contoso.sharepoint.com/sites/BotFiles"curl -H "Authorization: Bearer $TOKEN" \"https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles"# Response includes: "id": "contoso.sharepoint.com,guid1,guid2" -
Configurez OpenClaw :
{channels: {msteams: {// ... other config ...sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",},},}
Comportement de partage
Section intitulée « Comportement de partage »| Autorisation | Comportement de partage |
|---|---|
Sites.ReadWrite.All uniquement | Lien de partage à l’échelle de l’organisation (toute personne de l’organisation peut y accéder) |
Sites.ReadWrite.All + Chat.Read.All | Lien de partage par utilisateur (seuls les membres de la conversation peuvent y accéder) |
Le partage par utilisateur est plus sécurisé car seuls les participants à la conversation peuvent accéder au fichier. Si l’autorisation Chat.Read.All est manquante, le bot revient au partage à l’échelle de l’organisation.
Comportement de repli
Section intitulée « Comportement de repli »| Scénario | Résultat |
|---|---|
Conversation de groupe + fichier + sharePointSiteId configuré | Télécharger vers SharePoint, envoyer le lien de partage |
Conversation de groupe + fichier + aucun sharePointSiteId | Tenter le téléchargement vers OneDrive (peut échouer), envoyer uniquement le texte |
| Conversation personnelle + fichier | Flux FileConsentCard (fonctionne sans SharePoint) |
| N’importe quel contexte + image | Codé en base64 en ligne (fonctionne sans SharePoint) |
Emplacement de stockage des fichiers
Section intitulée « Emplacement de stockage des fichiers »Les fichiers téléchargés sont stockés dans un dossier /OpenClawShared/ de la bibliothèque de documents par défaut du site SharePoint configuré.
Sondages (Cartes adaptatives)
Section intitulée « Sondages (Cartes adaptatives) »OpenClaw envoie les sondages Teams sous forme de Cartes adaptatives (il n’y a pas d’API de sondage Teams native).
- CLI : CLI
openclaw message poll --channel msteams --target conversation:<id> ... - Les votes sont enregistrés par la passerelle dans
~/.openclaw/msteams-polls.json. - La passerelle doit rester en ligne pour enregistrer les votes.
- Les sondages ne publient pas encore automatiquement de résumés des résultats (inspectez le fichier de stockage si nécessaire).
Cartes de présentation
Section intitulée « Cartes de présentation »Envoyez des charges utiles de présentation sémantique aux utilisateurs ou conversations Teams en utilisant l’outil message, la CLI, ou la livraison de réponse normale. OpenClaw les rend sous forme de cartes adaptatives Teams à partir du contrat de présentation générique.
Le paramètre presentation accepte des blocs sémantiques. Lorsque presentation est fourni, le texte du message est optionnel. Les boutons s’affichent sous forme d’actions d’envoi ou d’URL de carte adaptative. Les menus de sélection ne sont pas encore natifs dans le moteur de rendu Teams, donc OpenClaw les rétrograde en texte lisible avant la livraison.
Outil de l’agent :
{ action: "send", channel: "msteams", target: "user:<id>", presentation: { title: "Hello", blocks: [{ type: "text", text: "Hello!" }], },}CLI :
openclaw message send --channel msteams \ --presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello!"}]}'Pour plus de détails sur les formats cibles, voir Formats cibles ci-dessous.
Formats cibles
Section intitulée « Formats cibles »Les cibles MSTeams utilisent des préfixes pour distinguer les utilisateurs et les conversations :
| Type de cible | Format | Exemple |
|---|---|---|
| Utilisateur (par ID) | user:<aad-object-id> | user:40a1a0ed-4ff2-4164-a219-55518990c197 |
| Utilisateur (par nom) | user:<display-name> | user:John SmithAPI (nécessite l’API Graph) |
| Groupe/channel | conversation:<conversation-id> | conversation:19:[email protected] |
| Groupe/channel (brut) | <conversation-id> | 19:[email protected] (si contient @thread) |
Exemples de CLI :
# Send to a user by IDopenclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"
# Send to a user by display name (triggers Graph API lookup)openclaw message send --channel msteams --target "user:John Smith" --message "Hello"
# Send to a group chat or channelopenclaw message send --channel msteams --target "conversation:19:[email protected]" --message "Hello"
# Send a presentation card to a conversation --presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello"}]}'Exemples d’outil d’agent :
{ action: "send", channel: "msteams", target: "user:John Smith", message: "Hello!",}{ action: "send", channel: "msteams", presentation: { title: "Hello", blocks: [{ type: "text", text: "Hello" }], },}Messagerie proactive
Section intitulée « Messagerie proactive »- Les messages proactifs ne sont possibles qu’après qu’un utilisateur a interagi, car nous stockons les références de conversation à ce moment-là.
- Voir
/gateway/configurationpourdmPolicyet le filtrage par liste blanche.
ID d’équipe et de canal (Piège courant)
Section intitulée « ID d’équipe et de canal (Piège courant) »Le paramètre de requête groupId dans les URL Teams n’EST PAS l’ID de l’équipe utilisé pour la configuration. Extrayez plutôt les ID du chemin de l’URL :
URL de l’équipe :
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=... └────────────────────────────┘ Team conversation ID (URL-decode this)URL du canal :
https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=... └─────────────────────────┘ Channel ID (URL-decode this)Pour la configuration :
- Clé d’équipe = segment de chemin après
/team/(URL décodé, par ex.,19:[email protected]; les anciens locataires peuvent afficher@thread.skype, qui est également valide) - Clé de channel = segment de chemin après
/channel/(URL décodé) - Ignorer le paramètre de requête
groupIdpour le routage OpenClaw. Il s’agit de l’ID de groupe Microsoft Entra, et non de l’ID de conversation du Bot Framework utilisé dans les activités Teams entrantes.
Canaux privés
Section intitulée « Canaux privés »Les bots ont une prise en charge limitée dans les canaux privés :
| Fonctionnalité | Canaux standard | Canaux privés |
|---|---|---|
| Installation du bot | Oui | Limitée |
| Messages en temps réel (webhook) | Oui | Peut ne pas fonctionner |
| Autorisations RSC | Oui | Peut se comporter différemment |
| @mentions | Oui | Si le bot est accessible |
| Historique du Graph API | Oui | Oui (avec autorisations) |
Solutions de contournement si les canaux privés ne fonctionnent pas :
- Utilisez les canaux standard pour les interactions avec le bot
- Utilisez les DMs - les utilisateurs peuvent toujours envoyer un message directement au bot
- Utiliser le Graph API pour l’accès historique (nécessite
ChannelMessage.Read.All)
Résolution des problèmes
Section intitulée « Résolution des problèmes »Problèmes courants
Section intitulée « Problèmes courants »- Images ne s’affichant pas dans les canaux : Permissions Graph ou consentement administratif manquant. Réinstallez l’application Teams et quittez/rouvrez entièrement Teams.
- Pas de réponse dans le channel : les mentions sont requises par défaut ; définissez
channels.msteams.requireMention=falseou configurez par équipe/channel. - Inadéquation de version (Teams affiche toujours l’ancien manifeste) : supprimez et rajoutez l’application et quittez entièrement Teams pour actualiser.
- 401 Non autorisé depuis le webhook : Attendu lors de tests manuels sans JWT Azure - signifie que le point de terminaison est accessible mais que l’authentification a échoué. Utilisez Azure Web Chat pour tester correctement.
Erreurs de téléchargement de manifeste
Section intitulée « Erreurs de téléchargement de manifeste »- “Icon file cannot be empty” : Le manifeste fait référence à des fichiers d’icônes de 0 octet. Créez des icônes PNG valides (32x32 pour
outline.png, 192x192 pourcolor.png). - « webApplicationInfo.Id déjà utilisé » : L’application est toujours installée dans une autre équipe/conversation. Trouvez-la et désinstallez-la d’abord, ou attendez 5 à 10 minutes pour la propagation.
- “Something went wrong” lors du téléchargement : Téléchargez plutôt via https://admin.teams.microsoft.com, ouvrez les outils de développement du navigateur (F12) → onglet Réseau, et vérifiez le corps de la réponse pour l’erreur réelle.
- Échec du chargement latéral : Essayez « Charger une application dans le catalogue d’applications de votre organisation » au lieu de « Charger une application personnalisée » ; cela contourne souvent les restrictions de chargement latéral.
Autorisations RSC non fonctionnelles
Section intitulée « Autorisations RSC non fonctionnelles »- Vérifiez que
webApplicationInfo.idcorrespond exactement à l’ID d’application de votre bot - Téléchargez à nouveau l’application et réinstallez-la dans l’équipe/la conversation
- Vérifiez si l’administrateur de votre organisation a bloqué les autorisations RSC
- Confirmez que vous utilisez la bonne portée :
ChannelMessage.Read.Grouppour les équipes,ChatMessage.Read.Chatpour les conversations de groupe
Références
Section intitulée « Références »- Create Azure Bot - Guide de configuration du bot Azure
- Teams Developer Portal - créer/gérer les applications Teams
- Teams app manifest schema
- Receive channel messages with RSC
- RSC permissions reference
- Teams bot file handling (channel/groupe nécessite Graph)
- Proactive messaging
- @microsoft/teams.cli - Teams CLI pour la gestion des bots
Connexes
Section intitulée « Connexes »- Vue d’ensemble des canaux - tous les canaux pris en charge
- Appairage - authentification DM et flux d’appairage
- Groupes - comportement de la conversation de groupe et filtrage des mentions
- Routage de canal - routage de session pour les messages
- Sécurité - modèle d’accès et durcissement