Mainstream messaging
Microsoft Teams
Statut : les pièces jointes texte + DM sont prises en charge ; l’envoi de fichiers dans les canaux/groupes nécessite sharePointSiteId + les autorisations Graph (voir Envoi de fichiers dans les discussions de groupe). Les sondages sont envoyés via des cartes adaptatives. Les actions de message exposent explicitement upload-file pour les envois centrés sur les fichiers.
Plugin intégré
Microsoft Teams est livré comme Plugin intégré dans les versions actuelles d’OpenClaw ; aucune installation séparée n’est donc 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/msteams
Utilisez le package nu pour suivre l’étiquette de version officielle actuelle. N’épinglez une version exacte que si vous avez besoin d’une installation reproductible.
Checkout local (lors d’une exécution depuis un dépôt git) :
openclaw plugins install ./path/to/local/msteams-plugin
Détails : Plugins
Configuration rapide
@microsoft/teams.cli gère l’enregistrement 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@preview
teams login
teams status # verify you're logged in and see your tenant info
2. Démarrer un tunnel (Teams ne peut pas atteindre localhost)
Installez et authentifiez la CLI devtunnel si ce n’est pas déjà fait (guide de démarrage).
# One-time setup (persistent URL across sessions):
devtunnel create my-openclaw-bot --allow-anonymous
devtunnel 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/messages
Alternatives : ngrok http 3978 ou tailscale funnel 3978 (mais ces solutions peuvent changer d’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 un secret client
- Construit et téléverse un manifeste d’application Teams (avec icônes)
- Enregistre le bot (géré par Teams par défaut - aucun abonnement Azure nécessaire)
La sortie affichera CLIENT_ID, CLIENT_SECRET, TENANT_ID et un ID d’application Teams - notez-les pour les étapes suivantes. Elle propose également d’installer directement l’application dans Teams.
4. Configurer OpenClaw avec les identifiants issus 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. Installer 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-link
6. Vérifier que tout fonctionne
teams app doctor <teamsAppId>
Cette commande 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 de production, envisagez d’utiliser l’authentification fédérée (certificat ou identité managée) au lieu de secrets client.
Objectifs
- Discuter avec OpenClaw via les DM Teams, les discussions de groupe ou les canaux.
- Garder un routage déterministe : les réponses reviennent toujours au canal d’où elles proviennent.
- Utiliser par défaut un comportement de canal sûr (mentions requises sauf configuration contraire).
Écritures de configuration
Par défaut, Microsoft Teams est autorisé à écrire les mises à jour de configuration déclenchées par /config set|unset (nécessite commands.config: true).
Désactivez avec :
{
channels: { msteams: { configWrites: false } },
}
Contrôle d’accès (DM + 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.- Ne vous fiez pas à la correspondance UPN/nom d’affichage pour les listes d’autorisation - ils peuvent changer. OpenClaw désactive par défaut la correspondance directe par nom ; activez-la explicitement avec
channels.msteams.dangerouslyAllowNameMatching: true. - L’assistant peut résoudre les noms en ID via Microsoft Graph lorsque les identifiants le permettent.
Accès 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 peuvent déclencher dans les discussions de groupe/canaux (avec repli surchannels.msteams.allowFrom).- Définissez
groupPolicy: "open"pour autoriser n’importe quel membre (toujours contrôlé par mention par défaut). - Pour n’autoriser aucun canal, définissez
channels.msteams.groupPolicy: "disabled".
Exemple :
{
channels: {
msteams: {
groupPolicy: "allowlist",
groupAllowFrom: ["[email protected]"],
},
},
}
Teams + liste d’autorisation de canaux
- Limitez la portée des réponses de groupe/canal en listant les équipes et les canaux sous
channels.msteams.teams. - Les clés doivent utiliser des ID de conversation Teams stables provenant des liens Teams, et non des noms d’affichage modifiables.
- Lorsque
groupPolicy="allowlist"et qu’une liste d’autorisation d’équipes est présente, seules les équipes/canaux listés sont acceptés (contrôlé par mention). - L’assistant de configuration accepte les entrées
Team/Channelet les stocke pour vous. - Au démarrage, OpenClaw résout les noms d’équipe/canal et de liste d’autorisation utilisateur en ID (lorsque les autorisations Graph le permettent) et journalise la correspondance ; les noms d’équipe/canal non résolus sont conservés tels que saisis, mais ignorés par défaut pour le routage, sauf si
channels.msteams.dangerouslyAllowNameMatching: trueest activé.
Exemple :
{
channels: {
msteams: {
groupPolicy: "allowlist",
teams: {
"My Team": {
channels: {
General: { requireMention: true },
},
},
},
},
},
}
Configuration manuelle (sans la CLI Teams)
Si vous ne pouvez pas utiliser la CLI Teams, vous pouvez configurer le bot manuellement via le portail Azure.
Fonctionnement
- Assurez-vous que le Plugin Microsoft Teams est disponible (intégré dans les versions actuelles).
- Créez un Azure Bot (ID d’application + secret + ID de locataire).
- Construisez un package d’application Teams qui référence le bot et inclut les autorisations RSC ci-dessous.
- Téléversez/installez l’application Teams dans une équipe (ou dans la portée personnelle pour les DM).
- Configurez
msteamsdans~/.openclaw/openclaw.json(ou avec des variables d’environnement) et démarrez le gateway. - Le gateway écoute par défaut le trafic Webhook Bot Framework sur
/api/messages.
Étape 1 : Créer Azure Bot
-
Accédez à Créer Azure Bot
-
Remplissez l’onglet Basics :
Champ Valeur Bot handle Le nom de votre bot, par ex. openclaw-msteams(doit être unique)Subscription Sélectionnez votre abonnement Azure Resource group Créez-en un nouveau ou utilisez-en un existant Pricing tier Free pour dev/test Type of App Single Tenant (recommandé - voir la note ci-dessous) Creation type Create new Microsoft App ID
- Cliquez sur Review + create → Create (attendez environ 1 à 2 minutes)
Étape 2 : Obtenir les identifiants
- Accédez à votre ressource Azure Bot → Configuration
- Copiez Microsoft App ID → il s’agit de votre
appId - Cliquez sur Manage Password → accédez à l’inscription d’application
- Sous Certificates & secrets → New client secret → copiez la Value → il s’agit de votre
appPassword - Accédez à Overview → copiez Directory (tenant) ID → il s’agit de votre
tenantId
Étape 3 : Configurer le point de terminaison de messagerie
- Dans Azure Bot → Configuration
- Définissez Messaging endpoint sur votre URL de Webhook :
- Production :
https://your-domain.com/api/messages - Développement local : utilisez un tunnel (voir Développement local ci-dessous)
- Production :
Étape 4 : Activer le canal Teams
- Dans Azure Bot → Channels
- Cliquez sur Microsoft Teams → Configurer → Enregistrer
- Acceptez les conditions d’utilisation
Étape 5 : Construire le manifeste d’application Teams
- Incluez une entrée
botavecbotId = <App ID>. - Portées :
personal,team,groupChat. supportsFiles: true(requis pour la gestion des fichiers dans la portée personnelle).- Ajoutez les autorisations RSC (voir Autorisations RSC).
- Créez des icônes :
outline.png(32x32) etcolor.png(192x192). - Compressez les trois fichiers ensemble :
manifest.json,outline.png,color.png.
É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
Le canal Teams démarre automatiquement lorsque le Plugin est disponible et qu’une configuration msteams existe avec les identifiants.
Authentification fédérée (certificat plus identité managée)
Ajouté en 2026.4.11
Pour les déploiements de production, OpenClaw prend en charge l’authentification fédérée comme alternative plus sûre aux secrets client. Deux méthodes sont disponibles :
Option A : Authentification basée sur 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 → Certificates & secrets → Certificates → téléversez le certificat public.
Configuration :
{
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é managée Azure
Utilisez Azure Managed Identity 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) lorsqu’une identité managée est disponible.
Fonctionnement :
- Le pod/la VM du bot possède une identité managée (assignée par le système ou par l’utilisateur).
- Un identifiant d’identité fédérée lie l’identité managée à l’inscription d’application Entra ID.
- À l’exécution, OpenClaw utilise
@azure/identitypour acquérir des jetons depuis le point de terminaison Azure IMDS (169.254.169.254). - Le jeton est transmis au SDK Teams pour l’authentification du bot.
Prérequis :
- Infrastructure Azure avec identité managée activée (identité de charge de travail AKS, App Service, VM)
- Identifiant d’identité fédérée créé sur l’inscription d’application Entra ID
- Accès réseau à IMDS (
169.254.169.254:80) depuis le pod/la VM
Configuration (identité managée assigné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é managée affecté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é affectée par l’utilisateur)
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 un identifiant d’identité fédérée sur l’inscription d’application Entra ID :
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: v1 kind: ServiceAccount metadata: name: my-bot-sa annotations: azure.workload.identity/client-id: "<APP_CLIENT_ID>" -
Ajoutez un libellé au 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
| 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é managé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 (tunnel)
Teams ne peut pas atteindre localhost. Utilisez un tunnel de développement persistant afin que votre URL reste la même entre les sessions :
# One-time setup:
devtunnel create my-openclaw-bot --allow-anonymous
devtunnel port create my-openclaw-bot -p 3978 --protocol auto
# Each dev session:
devtunnel host my-openclaw-bot
Alternatives : 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
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 :
- Installez l’application Teams (utilisez le lien d’installation depuis
teams app get <id> --install-link) - Trouvez le bot dans Teams et envoyez-lui un DM
- Vérifiez les journaux du Gateway pour l’activité entrante
Variables d’environnement
Toutes les clés de configuration peuvent aussi être définies au moyen de variables d’environnement :
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_IDMSTEAMS_AUTH_TYPE(facultatif :"secret"ou"federated")MSTEAMS_CERTIFICATE_PATH(fédéré + certificat)MSTEAMS_CERTIFICATE_THUMBPRINT(facultatif, non requis pour l’authentification)MSTEAMS_USE_MANAGED_IDENTITY(fédéré + identité managée)MSTEAMS_MANAGED_IDENTITY_CLIENT_ID(IM affectée par l’utilisateur uniquement)
Action d’informations sur les membres
OpenClaw expose une action member-info basée sur Graph pour Microsoft Teams, afin que les agents et les automatisations puissent résoudre les détails des membres d’un canal (nom d’affichage, e-mail, rôle) directement depuis Microsoft Graph.
Exigences :
- Autorisation RSC
Member.Read.Group(déjà présente dans le manifeste recommandé) - Pour les recherches entre équipes : autorisation d’application Graph
User.Read.Allavec consentement administrateur
L’action est contrôlée par channels.msteams.actions.memberInfo (par défaut : activée lorsque les identifiants Graph sont disponibles).
Contexte de l’historique
channels.msteams.historyLimitcontrôle le nombre de messages récents de canal/groupe enveloppés dans le prompt.- Repli sur
messages.groupChat.historyLimit. Définissez0pour désactiver (50 par défaut). - L’historique de fil récupéré est filtré par listes d’autorisation d’expéditeurs (
allowFrom/groupAllowFrom), de sorte que l’amorçage du contexte de fil inclut uniquement les messages provenant d’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 que reçu. - Autrement dit, les listes d’autorisation contrôlent qui peut déclencher l’agent ; seuls certains chemins de contexte supplémentaire 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)
Voici les autorisations resourceSpecific existantes dans notre manifeste d’application Teams. Elles s’appliquent uniquement dans l’équipe/la conversation où l’application est installée.
Pour les canaux (portée é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 discussion de groupe sans @mention
Pour ajouter des autorisations RSC via la CLI Teams :
teams app rsc add <teamsAppId> ChannelMessage.Read.Group --type Application
Exemple de manifeste Teams (expurgé)
Exemple minimal et valide avec les champs requis. 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" },
],
},
},
}
Précautions concernant le 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 la portée personnelle.authorization.permissions.resourceSpecificdoit inclure la lecture/l’envoi de canal si vous souhaitez du trafic de canal.
Mettre à jour 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 manifest
teams app manifest download <teamsAppId> manifest.json
# Edit manifest.json locally...
teams app manifest upload manifest.json <teamsAppId>
# Version is auto-bumped if content changed
Après la mise à jour, réinstallez l’application dans chaque équipe pour que les nouvelles autorisations prennent effet, puis quittez complètement Teams et relancez-le (pas seulement fermer la fenêtre) afin d’effacer les métadonnées d’application mises 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éversez le nouveau fichier zip :
- Centre d’administration Teams : Applications Teams → Gérer les applications → trouvez votre application → Téléverser une nouvelle version
- Chargement indépendant : Dans Teams → Applications → Gérer vos applications → Téléverser une application personnalisée
Capacités : RSC uniquement ou Graph
Avec Teams RSC uniquement (application installée, aucune autorisation API Graph)
Fonctionne :
- Lire le contenu texte des messages de canal.
- Envoyer du contenu texte dans les messages de canal.
- Recevoir les pièces jointes de fichier personnelles (DM).
Ne fonctionne PAS :
- Contenus d’image ou de fichier de canal/groupe (la charge utile inclut uniquement un stub HTML).
- Téléchargement des pièces jointes stockées dans SharePoint/OneDrive.
- Lecture de l’historique des messages (au-delà de l’événement Webhook en direct).
Avec Teams RSC + autorisations d’application Microsoft Graph
Ajoute :
- Téléchargement des contenus hébergés (images collées dans les messages).
- Téléchargement des pièces jointes de fichiers stockées dans SharePoint/OneDrive.
- Lecture de l’historique des messages de canal/discussion via Graph.
RSC ou API Graph
| Capacité | Autorisations RSC | API Graph |
|---|---|---|
| Messages en temps réel | Oui (via Webhook) | Non (interrogation uniquement) |
| Messages historiques | Non | Oui (peut interroger l’historique) |
| Complexité de configuration | Manifeste d’application uniquement | Nécessite consentement administrateur + flux de jeton |
| Fonctionne hors ligne | Non (doit être en cours d’exécution) | Oui (interrogeable à tout moment) |
En résumé : RSC sert à l’écoute en temps réel ; l’API Graph sert à l’accès historique. Pour rattraper les messages manqués pendant une période hors ligne, vous avez besoin de l’API Graph avec ChannelMessage.Read.All (nécessite un consentement administrateur).
Média + historique activés par Graph (requis pour les canaux)
Si vous avez besoin d’images/fichiers dans les canaux ou si vous voulez récupérer l’historique des messages, vous devez activer les autorisations Microsoft Graph et accorder le consentement administrateur.
- Dans Inscription d’application Entra ID (Azure AD), ajoutez les autorisations d’application Microsoft Graph :
ChannelMessage.Read.All(pièces jointes de canal + historique)Chat.Read.AllouChatMessage.Read.All(discussions de groupe)
- Accordez le consentement administrateur pour le locataire.
- Augmentez la version du manifeste de l’application Teams, téléversez-le à nouveau, puis réinstallez l’application dans Teams.
- Quittez complètement Teams et relancez-le afin d’effacer les métadonnées d’application mises en cache.
Autorisation supplémentaire pour les mentions utilisateur : Les @mentions d’utilisateurs fonctionnent directement pour les utilisateurs présents dans la conversation. Toutefois, si vous souhaitez rechercher et mentionner dynamiquement des utilisateurs qui ne sont pas dans la conversation actuelle, ajoutez l’autorisation User.Read.All (Application) et accordez le consentement administrateur.
Limites connues
Expirations de délai Webhook
Teams livre les messages via un Webhook HTTP. Si le traitement prend trop de temps (par exemple, réponses LLM lentes), vous pouvez voir :
- Des expirations de délai du Gateway
- Teams qui réessaie le message (provoquant des doublons)
- Des réponses abandonnées
OpenClaw gère cela en retournant rapidement et en envoyant les réponses de façon proactive, mais des réponses très lentes peuvent encore causer des problèmes.
Mise en forme
Le Markdown Teams est plus limité que celui de 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 Adaptive Cards sont prises en charge pour les sondages et les envois de présentation sémantique (voir ci-dessous)
Configuration
Paramètres clés (voir /gateway/configuration pour les modèles de canaux partagés) :
channels.msteams.enabled: activer/désactiver le canal.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 : pairing)channels.msteams.allowFrom: liste d’autorisation pour les MP (ID d’objets AAD recommandés). L’assistant résout les noms en ID pendant la configuration lorsque l’accès Graph est disponible.channels.msteams.dangerouslyAllowNameMatching: bascule de dernier recours pour réactiver la correspondance mutable par UPN/nom d’affichage et le routage direct par nom d’équipe/canal.channels.msteams.textChunkLimit: taille des fragments de texte sortants.channels.msteams.chunkMode:length(par défaut) ounewlinepour découper sur les lignes vides (limites de paragraphes) avant le découpage par longueur.channels.msteams.mediaAllowHosts: liste d’autorisation pour les hôtes de pièces jointes entrantes (par défaut, domaines Microsoft/Teams).channels.msteams.mediaAuthAllowHosts: liste d’autorisation pour joindre des en-têtes Authorization lors des nouvelles tentatives média (par défaut, hôtes Graph + Bot Framework).channels.msteams.requireMention: exiger une @mention dans les canaux/groupes (par défaut true).channels.msteams.replyStyle:thread | top-level(voir Style de réponse).channels.msteams.teams.<teamId>.replyStyle: remplacement par équipe.channels.msteams.teams.<teamId>.requireMention: remplacement par équipe.channels.msteams.teams.<teamId>.tools: remplacements par défaut de la politique d’outils par équipe (allow/deny/alsoAllow) utilisés lorsqu’un remplacement de canal est absent.channels.msteams.teams.<teamId>.toolsBySender: remplacements par défaut de la politique d’outils par expéditeur et par équipe (caractère générique"*"pris en charge).channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: remplacement par canal.channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: remplacement par canal.channels.msteams.teams.<teamId>.channels.<conversationId>.tools: remplacements de la politique d’outils par canal (allow/deny/alsoAllow).channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: remplacements de la politique d’outils par expéditeur et par canal (caractère générique"*"pris en charge).- Les clés
toolsBySenderdoivent utiliser des préfixes explicites :id:,e164:,username:,name:(les anciennes clés sans préfixe correspondent toujours uniquement àid:). channels.msteams.actions.memberInfo: activer ou désactiver l’action d’informations sur les membres basée sur Graph (par défaut : activée 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 (facultative, non requise pour l’authentification).channels.msteams.useManagedIdentity: activer l’authentification par identité managée (mode fédéré).channels.msteams.managedIdentityClientId: ID client de l’identité managée attribuée par l’utilisateur.channels.msteams.sharePointSiteId: ID du site SharePoint pour les téléversements de fichiers dans les discussions de groupe/canaux (voir Envoi de fichiers dans les discussions de groupe).
Routage et sessions
- Les clés de session suivent le format d’agent standard (voir /concepts/session) :
- Les messages directs partagent la session principale (
agent:<agentId>:<mainKey>). - Les messages de canal/groupe utilisent l’ID de conversation :
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- Les messages directs partagent la session principale (
Style de réponse : threads ou publications
Teams a récemment introduit deux styles d’interface de canal au-dessus du même modèle de données sous-jacent :
| Style | Description | replyStyle recommandé |
|---|---|---|
| Publications (classique) | Les messages apparaissent comme des cartes avec des réponses en fil dessous | thread (par défaut) |
| Threads (type Slack) | Les messages s’enchaînent linéairement, davantage comme Slack | top-level |
Le problème : l’API Teams n’expose pas le style d’interface utilisé par un canal. Si vous utilisez le mauvais replyStyle :
threaddans un canal de style Threads → les réponses apparaissent imbriquées de manière maladroitetop-leveldans un canal de style Publications → les réponses apparaissent comme des publications distinctes de premier niveau au lieu d’être dans le fil
Solution : configurez replyStyle par canal selon la façon dont le canal est configuré :
{
channels: {
msteams: {
replyStyle: "thread",
teams: {
"19:[email protected]": {
channels: {
"19:[email protected]": {
replyStyle: "top-level",
},
},
},
},
},
},
}
Pièces jointes et images
Limites actuelles :
- MP : les images et pièces jointes de fichiers 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 inclut seulement un extrait HTML, pas les octets réels du fichier. Des autorisations de l’API Graph sont requises pour télécharger les pièces jointes de canal.
- Pour les envois explicites orientés fichier, utilisez
action=upload-fileavecmedia/filePath/path; lemessagefacultatif devient le texte/commentaire d’accompagnement, etfilenameremplace le nom téléversé.
Sans autorisations Graph, les messages de canal contenant des images seront reçus comme texte uniquement (le contenu de l’image n’est pas accessible au bot).
Par défaut, OpenClaw télécharge uniquement les médias depuis des noms d’hôtes Microsoft/Teams. Remplacez avec channels.msteams.mediaAllowHosts (utilisez ["*"] pour autoriser n’importe quel hôte).
Les en-têtes Authorization ne sont ajoutés que pour les hôtes dans channels.msteams.mediaAuthAllowHosts (par défaut, hôtes Graph + Bot Framework). Gardez cette liste stricte (évitez les suffixes multi-locataires).
Envoi de fichiers dans les discussions de groupe
Les bots peuvent envoyer des fichiers dans les MP avec le flux FileConsentCard (intégré). Cependant, l’envoi de fichiers dans les discussions de groupe/canaux nécessite une configuration supplémentaire :
| Contexte | Mode d’envoi des fichiers | Configuration nécessaire |
|---|---|---|
| MP | FileConsentCard → l’utilisateur accepte → le bot téléverse | Fonctionne immédiatement |
| Discussions de groupe/canaux | Téléversement vers SharePoint → partage du lien | Nécessite sharePointSiteId + autorisations Graph |
| Images (tout contexte) | Encodage inline en Base64 | Fonctionne immédiatement |
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 Graph /me/drive ne fonctionne pas pour les identités d’application). Pour envoyer des fichiers dans les discussions de groupe/canaux, le bot les téléverse vers un site SharePoint et crée un lien de partage.
Configuration
-
Ajoutez les autorisations de l’API Graph dans Entra ID (Azure AD) → App Registration :
Sites.ReadWrite.All(Application) - téléverser des fichiers vers SharePointChat.Read.All(Application) - facultatif, active les liens de partage par utilisateur
-
Accordez le consentement administrateur pour le locataire.
-
Obtenez l’ID de votre site SharePoint :
# 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
| 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 discussion peuvent y accéder) |
Le partage par utilisateur est plus sécurisé, car seuls les participants à la discussion peuvent accéder au fichier. Si l’autorisation Chat.Read.All est absente, le bot revient à un partage à l’échelle de l’organisation.
Comportement de secours
| Scénario | Résultat |
|---|---|
Discussion de groupe + fichier + sharePointSiteId configuré |
Téléversement vers SharePoint, envoi du lien de partage |
Discussion de groupe + fichier + aucun sharePointSiteId |
Tentative de téléversement OneDrive (peut échouer), envoi du texte uniquement |
| Discussion personnelle + fichier | Flux FileConsentCard (fonctionne sans SharePoint) |
| Tout contexte + image | Encodage inline en Base64 (fonctionne sans SharePoint) |
Emplacement de stockage des fichiers
Les fichiers téléversés sont stockés dans un dossier /OpenClawShared/ dans la bibliothèque de documents par défaut du site SharePoint configuré.
Sondages (Adaptive Cards)
OpenClaw envoie les sondages Teams sous forme d’Adaptive Cards (il n’existe pas d’API de sondage Teams native).
- CLI :
openclaw message poll --channel msteams --target conversation:<id> ... - Les votes sont enregistrés par le Gateway dans
~/.openclaw/msteams-polls.json. - Le Gateway doit rester en ligne pour enregistrer les votes.
- Les sondages ne publient pas encore automatiquement de résumés de résultats (inspectez le fichier de stockage si nécessaire).
Cartes de présentation
Envoyez des charges utiles de présentation sémantique aux utilisateurs ou conversations Teams à l’aide de l’outil message ou de la CLI. OpenClaw les rend sous forme d’Adaptive Cards 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 facultatif.
Outil d’agent :
{
action: "send",
channel: "msteams",
target: "user:<id>",
presentation: {
title: "Hello",
blocks: [{ type: "text", text: "Hello!" }],
},
}
CLI :
openclaw message send --channel msteams \
--target "conversation:19:[email protected]" \
--presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello!"}]}'
Pour les détails sur le format des cibles, voir Formats de cible ci-dessous.
Formats de cible
Les cibles MSTeams utilisent des préfixes pour distinguer les utilisateurs des 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 Smith (nécessite l’API Graph) |
| Groupe/canal | conversation:<conversation-id> |
conversation:19:[email protected] |
| Groupe/canal (brut) | <conversation-id> |
19:[email protected] (si contient @thread) |
Exemples CLI :
# Send to a user by ID
openclaw 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 channel
openclaw message send --channel msteams --target "conversation:19:[email protected]" --message "Hello"
# Send a presentation card to a conversation
openclaw message send --channel msteams --target "conversation:19:[email protected]" \
--presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello"}]}'
Exemples d'outils d'agent :
{
action: "send",
channel: "msteams",
target: "user:John Smith",
message: "Hello!",
}
{
action: "send",
channel: "msteams",
target: "conversation:19:[email protected]",
presentation: {
title: "Hello",
blocks: [{ type: "text", text: "Hello" }],
},
}
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à.
- Consultez
/gateway/configurationpourdmPolicyet le filtrage par liste d'autorisation.
IDs d'équipe et de canal (piège courant)
Le paramètre de requête groupId dans les URL Teams n'est PAS l'ID d'équipe utilisé pour la configuration. Extrayez plutôt les IDs depuis le chemin de l'URL :
URL d'équipe :
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
└────────────────────────────┘
Team conversation ID (URL-decode this)
URL de 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/(décodé depuis l'URL, par exemple19:[email protected]; les anciens tenants peuvent afficher@thread.skype, qui est également valide) - Clé de canal = segment de chemin après
/channel/(décodé depuis l'URL) - Ignorez le paramètre de requête
groupIdpour le routage OpenClaw. Il s'agit de l'ID de groupe Microsoft Entra, pas de l'ID de conversation Bot Framework utilisé dans les activités Teams entrantes.
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 | Peuvent se comporter différemment |
| @mentions | Oui | Si le bot est accessible |
| Historique Graph API | Oui | Oui (avec autorisations) |
Solutions de contournement si les canaux privés ne fonctionnent pas :
- Utilisez des canaux standard pour les interactions avec le bot
- Utilisez les messages directs : les utilisateurs peuvent toujours envoyer un message directement au bot
- Utilisez Graph API pour l'accès à l'historique (nécessite
ChannelMessage.Read.All)
Dépannage
Problèmes courants
- Images non affichées dans les canaux : autorisations Graph ou consentement administrateur manquants. Réinstallez l'application Teams et quittez/rouvrez complètement Teams.
- Aucune réponse dans le canal : les mentions sont requises par défaut ; définissez
channels.msteams.requireMention=falseou configurez par équipe/canal. - Incompatibilité de version (Teams affiche toujours l'ancien manifeste) : supprimez puis rajoutez l'application, et quittez complètement Teams pour actualiser.
- 401 Unauthorized depuis le webhook : attendu lors d'un test manuel sans JWT Azure ; cela signifie que l'endpoint est joignable, mais que l'authentification a échoué. Utilisez Azure Web Chat pour tester correctement.
Erreurs de téléversement du manifeste
- "Icon file cannot be empty" : le manifeste référence des fichiers d'icône de 0 octet. Créez des icônes PNG valides (32x32 pour
outline.png, 192x192 pourcolor.png). - "webApplicationInfo.Id already in use" : 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éversement : téléversez plutôt via https://admin.teams.microsoft.com, ouvrez les DevTools du navigateur (F12) → onglet Network, puis vérifiez le corps de la réponse pour l'erreur réelle.
- Échec du sideload : essayez "Upload an app to your org's app catalog" au lieu de "Upload a custom app" ; cela contourne souvent les restrictions de sideload.
Les autorisations RSC ne fonctionnent pas
- Vérifiez que
webApplicationInfo.idcorrespond exactement à l'App ID de votre bot - Retéléversez 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 le bon périmètre :
ChannelMessage.Read.Grouppour les équipes,ChatMessage.Read.Chatpour les conversations de groupe
Références
- Créer un bot Azure - guide de configuration d'Azure Bot
- Portail développeur Teams - créer/gérer des applications Teams
- Schéma du manifeste d'application Teams
- Recevoir des messages de canal avec RSC
- Référence des autorisations RSC
- Gestion des fichiers par les bots Teams (canal/groupe nécessite Graph)
- Messagerie proactive
- @microsoft/teams.cli - CLI Teams pour la gestion des bots
Connexe
- Vue d'ensemble des canaux - tous les canaux pris en charge
- Appairage - authentification par message direct et flux d'appairage
- Groupes - comportement des conversations de groupe et filtrage par mention
- Routage des canaux - routage des sessions pour les messages
- Sécurité - modèle d'accès et renforcement