Microsoft Teams (plugin)

« Vous qui entrez ici, abandonnez toute esperance. »

Mis a jour : 2026-01-21

Statut : le texte et les pieces jointes DM sont pris en charge ; l’envoi de fichiers dans les salons/groupes necessite sharePointSiteId + les permissions Graph (voir Envoi de fichiers dans les conversations de groupe). Les sondages sont envoyes via des Adaptive Cards.

Plugin requis

Microsoft Teams est distribue sous forme de plugin et n’est pas integre a l’installation de base.

Changement majeur (2026.1.15) : MS Teams a ete retire du coeur. Si vous l’utilisez, vous devez installer le plugin.

Explication : cela allege les installations de base et permet aux dependances MS Teams de se mettre a jour independamment.

Installation via CLI (registre npm) :

openclaw plugins install @openclaw/msteams

Checkout local (depuis un depot git) :

openclaw plugins install ./extensions/msteams

Si vous choisissez Teams lors de la configuration/onboarding et qu’un checkout git est detecte, OpenClaw proposera automatiquement le chemin d’installation local.

Details : Plugins

Configuration rapide (debutant)

  1. Installez le plugin Microsoft Teams.
  2. Creez un Azure Bot (App ID + secret client + tenant ID).
  3. Configurez OpenClaw avec ces identifiants.
  4. Exposez /api/messages (port 3978 par defaut) via une URL publique ou un tunnel.
  5. Installez le package d’application Teams et demarrez la gateway.

Configuration minimale :

{
  channels: {
    msteams: {
      enabled: true,
      appId: "<APP_ID>",
      appPassword: "<APP_PASSWORD>",
      tenantId: "<TENANT_ID>",
      webhook: { port: 3978, path: "/api/messages" },
    },
  },
}

Remarque : Les conversations de groupe sont bloquees par defaut (channels.msteams.groupPolicy: "allowlist"). Pour autoriser les reponses de groupe, definissez channels.msteams.groupAllowFrom (ou utilisez groupPolicy: "open" pour autoriser tout membre, avec filtrage par mention).

Objectifs

  • Discuter avec OpenClaw via les DMs Teams, les conversations de groupe ou les salons.
  • Garder un routage deterministe : les reponses retournent toujours au canal d’origine.
  • Adopter par defaut un comportement securise (mentions requises sauf configuration contraire).

Ecritures de configuration

Par defaut, Microsoft Teams est autorise a ecrire des mises a jour de configuration declenchees par /config set|unset (necessite commands.config: true).

Desactivation :

{
  channels: { msteams: { configWrites: false } },
}

Controle d’acces (DMs + groupes)

Acces DM

  • Par defaut : channels.msteams.dmPolicy = "pairing". Les expediteurs inconnus sont ignores jusqu’a approbation.
  • channels.msteams.allowFrom doit utiliser des identifiants d’objet AAD stables.
  • Les UPN/noms d’affichage sont modifiables ; la correspondance directe est desactivee par defaut et n’est activee qu’avec channels.msteams.dangerouslyAllowNameMatching: true.
  • L’assistant peut resoudre les noms en identifiants via Microsoft Graph lorsque les identifiants le permettent.

Acces groupe

  • Par defaut : channels.msteams.groupPolicy = "allowlist" (bloque sauf si vous ajoutez groupAllowFrom). Utilisez channels.defaults.groupPolicy pour remplacer la valeur par defaut lorsqu’elle n’est pas definie.
  • channels.msteams.groupAllowFrom controle quels expediteurs peuvent declencher le bot dans les conversations de groupe/salons (se replie sur channels.msteams.allowFrom).
  • Definissez groupPolicy: "open" pour autoriser tout membre (toujours filtre par mention par defaut).
  • Pour n’autoriser aucun salon, definissez channels.msteams.groupPolicy: "disabled".

Exemple :

{
  channels: {
    msteams: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["[email protected]"],
    },
  },
}

Liste d’autorisation equipes + salons

  • Delimitez les reponses de groupe/salon en listant les equipes et salons sous channels.msteams.teams.
  • Les cles doivent utiliser des identifiants d’equipe stables et des identifiants de conversation de salon.
  • Lorsque groupPolicy="allowlist" et qu’une liste d’autorisation d’equipes est presente, seuls les equipes/salons listes sont acceptes (filtres par mention).
  • L’assistant de configuration accepte les entrees Team/Channel et les enregistre pour vous.
  • Au demarrage, OpenClaw resout les noms d’equipe/salon et de liste d’autorisation utilisateur en identifiants (lorsque les permissions Graph le permettent) et journalise la correspondance ; les noms d’equipe/salon non resolus sont conserves tels quels mais ignores pour le routage par defaut, sauf si channels.msteams.dangerouslyAllowNameMatching: true est active.

Exemple :

{
  channels: {
    msteams: {
      groupPolicy: "allowlist",
      teams: {
        "My Team": {
          channels: {
            General: { requireMention: true },
          },
        },
      },
    },
  },
}

Fonctionnement

  1. Installez le plugin Microsoft Teams.
  2. Creez un Azure Bot (App ID + secret + tenant ID).
  3. Construisez un package d’application Teams qui reference le bot et inclut les permissions RSC ci-dessous.
  4. Uploadez/installez l’application Teams dans une equipe (ou en scope personnel pour les DMs).
  5. Configurez msteams dans ~/.openclaw/openclaw.json (ou variables d’environnement) et demarrez la gateway.
  6. La gateway ecoute le trafic webhook Bot Framework sur /api/messages par defaut.

Configuration Azure Bot (prerequis)

Avant de configurer OpenClaw, vous devez creer une ressource Azure Bot.

Etape 1 : creer un Azure Bot

  1. Rendez-vous sur Create Azure Bot

  2. Remplissez l’onglet Basics :

    ChampValeur
    Bot handleNom de votre bot, par ex. openclaw-msteams (doit etre unique)
    SubscriptionSelectionnez votre abonnement Azure
    Resource groupCreer un nouveau ou utiliser un existant
    Pricing tierFree pour dev/test
    Type of AppSingle Tenant (recommande - voir note ci-dessous)
    Creation typeCreate new Microsoft App ID

Remarque : La creation de nouveaux bots multi-tenant a ete deprecie apres le 2025-07-31. Utilisez Single Tenant pour les nouveaux bots.

  1. Cliquez sur Review + create → Create (attendez environ 1-2 minutes)

Etape 2 : obtenir les identifiants

  1. Allez sur votre ressource Azure Bot → Configuration
  2. Copiez Microsoft App ID → c’est votre appId
  3. Cliquez sur Manage Password → acces a l’App Registration
  4. Sous Certificates & secrets → New client secret → copiez la Value → c’est votre appPassword
  5. Allez dans Overview → copiez Directory (tenant) ID → c’est votre tenantId

Etape 3 : configurer le point de terminaison de messagerie

  1. Dans Azure Bot → Configuration
  2. Definissez Messaging endpoint sur votre URL webhook :
    • Production : https://your-domain.com/api/messages
    • Dev local : utilisez un tunnel (voir Developpement local ci-dessous)

Etape 4 : activer le canal Teams

  1. Dans Azure Bot → Channels
  2. Cliquez sur Microsoft Teams → Configure → Save
  3. Acceptez les conditions d’utilisation

Developpement local (tunnel)

Teams ne peut pas atteindre localhost. Utilisez un tunnel pour le developpement local :

Option A : ngrok

ngrok http 3978
# Copiez l'URL https, par ex. https://abc123.ngrok.io
# Definissez le messaging endpoint sur : https://abc123.ngrok.io/api/messages

Option B : Tailscale Funnel

tailscale funnel 3978
# Utilisez votre URL Tailscale funnel comme messaging endpoint

Portail developpeur Teams (alternative)

Au lieu de creer manuellement un fichier ZIP de manifeste, vous pouvez utiliser le portail developpeur Teams :

  1. Cliquez sur + New app
  2. Remplissez les infos de base (nom, description, infos developpeur)
  3. Allez dans App features → Bot
  4. Selectionnez Enter a bot ID manually et collez votre Azure Bot App ID
  5. Cochez les scopes : Personal, Team, Group Chat
  6. Cliquez sur Distribute → Download app package
  7. Dans Teams : Apps → Manage your apps → Upload a custom app → selectionnez le ZIP

C’est souvent plus simple que de modifier des manifestes JSON a la main.

Test du bot

Option A : Azure Web Chat (verifier le webhook d’abord)

  1. Dans le portail Azure → votre ressource Azure Bot → Test in Web Chat
  2. Envoyez un message — vous devriez voir une reponse
  3. Cela confirme que votre point de terminaison webhook fonctionne avant la configuration Teams

Option B : Teams (apres installation de l’application)

  1. Installez l’application Teams (sideload ou catalogue organisationnel)
  2. Trouvez le bot dans Teams et envoyez un DM
  3. Verifiez les logs de la gateway pour l’activite entrante

Configuration (texte seul minimal)

  1. Installer le plugin Microsoft Teams

    • Depuis npm : openclaw plugins install @openclaw/msteams
    • Depuis un checkout local : openclaw plugins install ./extensions/msteams
  2. Enregistrement du bot

    • Creez un Azure Bot (voir ci-dessus) et notez :
      • App ID
      • Client secret (mot de passe de l’application)
      • Tenant ID (single-tenant)
  3. Manifeste de l’application Teams

    • Incluez une entree bot avec botId = <App ID>.
    • Scopes : personal, team, groupChat.
    • supportsFiles: true (requis pour la gestion des fichiers en scope personnel).
    • Ajoutez les permissions RSC (ci-dessous).
    • Creez les icones : outline.png (32x32) et color.png (192x192).
    • Compressez les trois fichiers : manifest.json, outline.png, color.png.
  4. Configurer OpenClaw

    {
      "msteams": {
        "enabled": true,
        "appId": "<APP_ID>",
        "appPassword": "<APP_PASSWORD>",
        "tenantId": "<TENANT_ID>",
        "webhook": { "port": 3978, "path": "/api/messages" }
      }
    }

    Vous pouvez aussi utiliser des variables d’environnement au lieu des cles de configuration :

    • MSTEAMS_APP_ID
    • MSTEAMS_APP_PASSWORD
    • MSTEAMS_TENANT_ID
  5. Point de terminaison du bot

    • Definissez le Messaging Endpoint de l’Azure Bot sur :
      • https://<host>:3978/api/messages (ou votre chemin/port choisi).
  6. Lancer la gateway

    • Le canal Teams demarre automatiquement lorsque le plugin est installe et que la configuration msteams existe avec les identifiants.

Contexte d’historique

  • channels.msteams.historyLimit controle le nombre de messages recents de salon/groupe inclus dans le prompt.
  • Se replie sur messages.groupChat.historyLimit. Definissez 0 pour desactiver (par defaut 50).
  • L’historique DM peut etre limite avec channels.msteams.dmHistoryLimit (tours utilisateur). Remplacements par utilisateur : channels.msteams.dms["<user_id>"].historyLimit.

Permissions RSC Teams actuelles (manifeste)

Voici les permissions resourceSpecific existantes dans notre manifeste d’application Teams. Elles ne s’appliquent qu’a l’interieur de l’equipe/conversation ou l’application est installee.

Pour les salons (scope equipe) :

  • ChannelMessage.Read.Group (Application) - recevoir tous les messages de salon sans @mention
  • ChannelMessage.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 conversations de groupe :

  • ChatMessage.Read.Chat (Application) - recevoir tous les messages de conversation de groupe sans @mention

Exemple de manifeste Teams (expurge)

Exemple minimal et valide avec les champs requis. Remplacez les identifiants et les URLs.

{
  "$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" }
      ]
    }
  }
}

Precautions pour le manifeste (champs obligatoires)

  • bots[].botId doit correspondre a l’App ID de l’Azure Bot.
  • webApplicationInfo.id doit correspondre a l’App ID de l’Azure Bot.
  • bots[].scopes doit inclure les surfaces que vous prevoyez d’utiliser (personal, team, groupChat).
  • bots[].supportsFiles: true est requis pour la gestion des fichiers en scope personnel.
  • authorization.permissions.resourceSpecific doit inclure la lecture/envoi de salon si vous voulez du trafic dans les salons.

Mettre a jour une application existante

Pour mettre a jour une application Teams deja installee (par ex. pour ajouter des permissions RSC) :

  1. Mettez a jour votre manifest.json avec les nouveaux parametres
  2. Incrementez le champ version (par ex. 1.0.0 → 1.1.0)
  3. Recompressez le manifeste avec les icones (manifest.json, outline.png, color.png)
  4. Uploadez le nouveau zip :
    • Option A (Teams Admin Center) : Teams Admin Center → Teams apps → Manage apps → trouvez votre application → Upload new version
    • Option B (Sideload) : Dans Teams → Apps → Manage your apps → Upload a custom app
  5. Pour les salons d’equipe : reinstallez l’application dans chaque equipe pour que les nouvelles permissions prennent effet
  6. Quittez completement Teams et relancez (pas seulement fermer la fenetre) pour vider les metadonnees d’application en cache

Capacites : RSC seul vs Graph

Avec RSC Teams uniquement (application installee, pas de permissions Graph API)

Fonctionne :

  • Lire le contenu texte des messages de salon.
  • Envoyer du contenu texte dans les salons.
  • Recevoir les pieces jointes personnelles (DM).

Ne fonctionne pas :

  • Le contenu des images ou fichiers de salon/groupe (le payload ne contient qu’un stub HTML).
  • Telecharger les pieces jointes stockees dans SharePoint/OneDrive.
  • Lire l’historique des messages (au-dela de l’evenement webhook en direct).

Avec RSC Teams + permissions Microsoft Graph Application

Ajoute :

  • Telechargement des contenus heberges (images collees dans les messages).
  • Telechargement des pieces jointes stockees dans SharePoint/OneDrive.
  • Lecture de l’historique des messages de salon/conversation via Graph.

RSC vs Graph API

CapacitePermissions RSCGraph API
Messages en temps reelOui (via webhook)Non (interrogation uniquement)
Messages historiquesNonOui (peut interroger l’historique)
Complexite de configManifeste app seulNecessite consentement admin + flux de token
Fonctionne hors ligneNon (doit etre actif)Oui (interrogation a tout moment)

En resume : RSC est pour l’ecoute en temps reel ; Graph API est pour l’acces historique. Pour rattraper les messages manques hors ligne, vous avez besoin de Graph API avec ChannelMessage.Read.All (necessite le consentement admin).

Medias + historique avec Graph (requis pour les salons)

Si vous avez besoin d’images/fichiers dans les salons ou souhaitez recuperer l’historique des messages, vous devez activer les permissions Microsoft Graph et accorder le consentement admin.

  1. Dans Entra ID (Azure AD) App Registration, ajoutez les permissions Application Microsoft Graph :
    • ChannelMessage.Read.All (pieces jointes de salon + historique)
    • Chat.Read.All ou ChatMessage.Read.All (conversations de groupe)
  2. Accordez le consentement admin pour le tenant.
  3. Incrementez la version du manifeste de l’application Teams, re-uploadez et reinstallez l’application dans Teams.
  4. Quittez completement Teams et relancez pour vider les metadonnees d’application en cache.

Permission supplementaire pour les mentions utilisateur : Les @mentions d’utilisateur fonctionnent directement pour les utilisateurs dans la conversation. Cependant, si vous souhaitez rechercher et mentionner dynamiquement des utilisateurs qui ne sont pas dans la conversation en cours, ajoutez la permission User.Read.All (Application) et accordez le consentement admin.

Limitations connues

Timeouts webhook

Teams livre les messages via webhook HTTP. Si le traitement prend trop de temps (par ex. reponses LLM lentes), vous pouvez voir :

  • Des timeouts de gateway
  • Teams reessayant le message (causant des doublons)
  • Des reponses perdues

OpenClaw gere cela en retournant rapidement et en envoyant les reponses de maniere proactive, mais les reponses tres lentes peuvent encore poser probleme.

Mise en forme

Le markdown Teams est plus limite que celui de Slack ou Discord :

  • La mise en forme de base fonctionne : gras, italique, code, liens
  • Le markdown complexe (tableaux, listes imbriquees) peut ne pas s’afficher correctement
  • Les Adaptive Cards sont prises en charge pour les sondages et les envois de cartes arbitraires (voir ci-dessous)

Configuration

Parametres cles (voir /gateway/configuration pour les modeles de configuration de canal partages) :

  • channels.msteams.enabled : activer/desactiver le canal.
  • channels.msteams.appId, channels.msteams.appPassword, channels.msteams.tenantId : identifiants du bot.
  • channels.msteams.webhook.port (par defaut 3978)
  • channels.msteams.webhook.path (par defaut /api/messages)
  • channels.msteams.dmPolicy : pairing | allowlist | open | disabled (par defaut : pairing)
  • channels.msteams.allowFrom : liste d’autorisation DM (identifiants d’objet AAD recommandes). L’assistant resout les noms en identifiants lors de la configuration lorsque l’acces Graph est disponible.
  • channels.msteams.dangerouslyAllowNameMatching : bascule derogatoire pour reactiver la correspondance mutable UPN/nom d’affichage et le routage direct par nom d’equipe/salon.
  • channels.msteams.textChunkLimit : taille des morceaux de texte sortant.
  • channels.msteams.chunkMode : length (par defaut) ou newline pour decouper aux lignes vides (limites de paragraphes) avant le decoupage par longueur.
  • channels.msteams.mediaAllowHosts : liste d’autorisation pour les hotes de pieces jointes entrantes (par defaut : domaines Microsoft/Teams).
  • channels.msteams.mediaAuthAllowHosts : liste d’autorisation pour attacher les en-tetes Authorization lors des reessais media (par defaut : hotes Graph + Bot Framework).
  • channels.msteams.requireMention : mention @ requise dans les salons/groupes (par defaut true).
  • channels.msteams.replyStyle : thread | top-level (voir Style de reponse).
  • channels.msteams.teams.<teamId>.replyStyle : remplacement par equipe.
  • channels.msteams.teams.<teamId>.requireMention : remplacement par equipe.
  • channels.msteams.teams.<teamId>.tools : remplacements de politique d’outils par defaut par equipe (allow/deny/alsoAllow) utilises lorsqu’un remplacement par salon est manquant.
  • channels.msteams.teams.<teamId>.toolsBySender : remplacements de politique d’outils par expediteur par equipe (joker "*" pris en charge).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle : remplacement par salon.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention : remplacement par salon.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.tools : remplacements de politique d’outils par salon (allow/deny/alsoAllow).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender : remplacements de politique d’outils par expediteur par salon (joker "*" pris en charge).
  • Les cles toolsBySender doivent utiliser des prefixes explicites : id:, e164:, username:, name: (les cles anciennes sans prefixe correspondent uniquement a id:).
  • channels.msteams.sharePointSiteId : identifiant de site SharePoint pour les uploads de fichiers dans les conversations de groupe/salons (voir Envoi de fichiers dans les conversations de groupe).

Routage et sessions

  • Les cles de session suivent le format standard d’agent (voir /concepts/session) :
    • Les messages directs partagent la session principale (agent:<agentId>:<mainKey>).
    • Les messages de salon/groupe utilisent l’identifiant de conversation :
      • agent:<agentId>:msteams:channel:<conversationId>
      • agent:<agentId>:msteams:group:<conversationId>

Style de reponse : fils vs publications

Teams a recemment introduit deux styles d’interface de salon sur le meme modele de donnees sous-jacent :

StyleDescriptionreplyStyle recommande
Publications (classic)Les messages apparaissent comme des cartes avec des reponses en fil en dessousthread (par defaut)
Fils (style Slack)Les messages deroulent lineairement, davantage comme Slacktop-level

Le probleme : L’API Teams n’expose pas quel style d’interface un salon utilise. Si vous utilisez le mauvais replyStyle :

  • thread dans un salon style fils → les reponses apparaissent imbriquees de maniere maladroite
  • top-level dans un salon style publications → les reponses apparaissent comme des publications separees au lieu d’etre dans le fil

Solution : Configurez replyStyle par salon en fonction de la configuration du salon :

{
  "msteams": {
    "replyStyle": "thread",
    "teams": {
      "19:[email protected]": {
        "channels": {
          "19:[email protected]": {
            "replyStyle": "top-level"
          }
        }
      }
    }
  }
}

Pieces jointes et images

Limitations actuelles :

  • DMs : Les images et pieces jointes fonctionnent via les API de fichiers du bot Teams.
  • Salons/groupes : Les pieces jointes resident dans le stockage M365 (SharePoint/OneDrive). Le payload webhook ne contient qu’un stub HTML, pas les octets reels du fichier. Les permissions Graph API sont necessaires pour telecharger les pieces jointes de salon.

Sans les permissions Graph, les messages de salon avec images seront recus en texte seul (le contenu de l’image n’est pas accessible au bot). Par defaut, OpenClaw ne telecharge les medias que depuis les noms d’hote Microsoft/Teams. Remplacez avec channels.msteams.mediaAllowHosts (utilisez ["*"] pour autoriser tout hote). Les en-tetes d’autorisation ne sont attaches que pour les hotes dans channels.msteams.mediaAuthAllowHosts (par defaut : hotes Graph + Bot Framework). Gardez cette liste stricte (evitez les suffixes multi-tenant).

Envoi de fichiers dans les conversations de groupe

Les bots peuvent envoyer des fichiers en DM via le flux FileConsentCard (integre). Cependant, l’envoi de fichiers dans les conversations de groupe/salons necessite une configuration supplementaire :

ContexteMode d’envoiConfiguration necessaire
DMsFileConsentCard → l’utilisateur accepte → le bot uploadeFonctionne directement
Conversations/salonsUpload vers SharePoint → lien de partageNecessite sharePointSiteId + permissions Graph
Images (tout contexte)Encodee en base64 inlineFonctionne directement

Pourquoi les conversations de groupe necessitent SharePoint

Les bots n’ont pas de drive OneDrive personnel (le point de terminaison Graph /me/drive ne fonctionne pas pour les identites application). Pour envoyer des fichiers dans les conversations de groupe/salons, le bot uploade vers un site SharePoint et cree un lien de partage.

Configuration

  1. Ajoutez les permissions Graph API dans Entra ID (Azure AD) → App Registration :

    • Sites.ReadWrite.All (Application) - upload de fichiers vers SharePoint
    • Chat.Read.All (Application) - optionnel, permet les liens de partage par utilisateur
  2. Accordez le consentement admin pour le tenant.

  3. Obtenez votre identifiant de site SharePoint :

    # Via Graph Explorer ou curl avec un token valide :
    curl -H "Authorization: Bearer $TOKEN" \
      "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}"
    
    # Exemple : pour un site sur "contoso.sharepoint.com/sites/BotFiles"
    curl -H "Authorization: Bearer $TOKEN" \
      "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles"
    
    # La reponse inclut : "id": "contoso.sharepoint.com,guid1,guid2"
  4. Configurez OpenClaw :

    {
      channels: {
        msteams: {
          // ... autre configuration ...
          sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
        },
      },
    }

Comportement de partage

PermissionComportement de partage
Sites.ReadWrite.All seulLien de partage organisationnel (tout le monde dans l’org peut acceder)
Sites.ReadWrite.All + Chat.Read.AllLien de partage par utilisateur (seuls les membres du chat peuvent acceder)

Le partage par utilisateur est plus securise car seuls les participants de la conversation peuvent acceder au fichier. Si la permission Chat.Read.All est manquante, le bot se replie sur le partage organisationnel.

Comportement de secours

ScenarioResultat
Conversation de groupe + fichier + sharePointSiteId configureUpload vers SharePoint, envoi du lien de partage
Conversation de groupe + fichier + pas de sharePointSiteIdTentative d’upload OneDrive (peut echouer), envoi texte seul
Chat personnel + fichierFlux FileConsentCard (fonctionne sans SharePoint)
Tout contexte + imageEncodee en base64 inline (fonctionne sans SharePoint)

Emplacement des fichiers stockes

Les fichiers uploades sont stockes dans un dossier /OpenClawShared/ dans la bibliotheque de documents par defaut du site SharePoint configure.

Sondages (Adaptive Cards)

OpenClaw envoie les sondages Teams sous forme d’Adaptive Cards (il n’y a pas d’API de sondage native Teams).

  • CLI : openclaw message poll --channel msteams --target conversation:<id> ...
  • Les votes sont enregistres par la gateway dans ~/.openclaw/msteams-polls.json.
  • La gateway doit rester en ligne pour enregistrer les votes.
  • Les sondages ne publient pas encore automatiquement de resume des resultats (inspectez le fichier de stockage si necessaire).

Adaptive Cards (arbitraires)

Envoyez tout JSON Adaptive Card aux utilisateurs ou conversations Teams via l’outil message ou la CLI.

Le parametre card accepte un objet JSON Adaptive Card. Lorsque card est fourni, le texte du message est optionnel.

Outil agent :

{
  "action": "send",
  "channel": "msteams",
  "target": "user:<id>",
  "card": {
    "type": "AdaptiveCard",
    "version": "1.5",
    "body": [{ "type": "TextBlock", "text": "Hello!" }]
  }
}

CLI :

openclaw message send --channel msteams \
  --target "conversation:19:[email protected]" \
  --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}'

Voir la documentation Adaptive Cards pour le schema et les exemples. Pour les details des formats de cible, voir Formats de cible ci-dessous.

Formats de cible

Les cibles MSTeams utilisent des prefixes pour distinguer les utilisateurs des conversations :

Type de cibleFormatExemple
Utilisateur (par ID)user:<aad-object-id>user:40a1a0ed-4ff2-4164-a219-55518990c197
Utilisateur (par nom)user:<display-name>user:John Smith (necessite Graph API)
Groupe/salonconversation:<conversation-id>conversation:19:[email protected]
Groupe/salon (brut)<conversation-id>19:[email protected] (si contient @thread)

Exemples CLI :

# Envoyer a un utilisateur par ID
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"

# Envoyer a un utilisateur par nom d'affichage (declenche une recherche Graph API)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"

# Envoyer a une conversation de groupe ou un salon
openclaw message send --channel msteams --target "conversation:19:[email protected]" --message "Hello"

# Envoyer une Adaptive Card a une conversation
openclaw message send --channel msteams --target "conversation:19:[email protected]" \
  --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}'

Exemples outil agent :

{
  "action": "send",
  "channel": "msteams",
  "target": "user:John Smith",
  "message": "Hello!"
}
{
  "action": "send",
  "channel": "msteams",
  "target": "conversation:19:[email protected]",
  "card": {
    "type": "AdaptiveCard",
    "version": "1.5",
    "body": [{ "type": "TextBlock", "text": "Hello" }]
  }
}

Remarque : Sans le prefixe user:, les noms correspondent par defaut a la resolution groupe/equipe. Utilisez toujours user: lorsque vous ciblez des personnes par nom d’affichage.

Messagerie proactive

  • Les messages proactifs ne sont possibles qu’apres qu’un utilisateur a interagi, car les references de conversation sont stockees a ce moment-la.
  • Voir /gateway/configuration pour la politique dmPolicy et le filtrage par liste d’autorisation.

Identifiants d’equipe et de salon (piege courant)

Le parametre de requete groupId dans les URLs Teams n’est PAS l’identifiant d’equipe utilise pour la configuration. Extrayez les identifiants du chemin de l’URL :

URL d’equipe :

https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
                                    └────────────────────────────┘
                                    Team ID (decodez l'URL)

URL de salon :

https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
                                      └─────────────────────────┘
                                      Channel ID (decodez l'URL)

Pour la configuration :

  • Team ID = segment de chemin apres /team/ (decode, par ex. 19:[email protected])
  • Channel ID = segment de chemin apres /channel/ (decode)
  • Ignorez le parametre de requete groupId

Salons prives

Les bots ont un support limite dans les salons prives :

FonctionnaliteSalons standardsSalons prives
Installation du botOuiLimitee
Messages temps reel (webhook)OuiPeut ne pas fonctionner
Permissions RSCOuiComportement different
@mentionsOuiSi le bot est accessible
Historique Graph APIOuiOui (avec permissions)

Solutions si les salons prives ne fonctionnent pas :

  1. Utilisez les salons standards pour les interactions avec le bot
  2. Utilisez les DMs — les utilisateurs peuvent toujours envoyer un message direct au bot
  3. Utilisez Graph API pour l’acces historique (necessite ChannelMessage.Read.All)

Depannage

Problemes courants

  • Images non affichees dans les salons : permissions Graph ou consentement admin manquants. Reinstallez l’application Teams et quittez/rouvrez completement Teams.
  • Pas de reponses dans un salon : les mentions sont requises par defaut ; definissez channels.msteams.requireMention=false ou configurez par equipe/salon.
  • Decalage de version (Teams affiche encore l’ancien manifeste) : supprimez + re-ajoutez l’application et quittez completement Teams pour rafraichir.
  • 401 Unauthorized du webhook : Attendu lors de tests manuels sans JWT Azure — signifie que le point de terminaison est accessible mais l’authentification a echoue. Utilisez Azure Web Chat pour tester correctement.

Erreurs d’upload de manifeste

  • “Icon file cannot be empty” : Le manifeste reference des fichiers d’icone de 0 octet. Creez des icones PNG valides (32x32 pour outline.png, 192x192 pour color.png).
  • “webApplicationInfo.Id already in use” : L’application est encore installee dans une autre equipe/conversation. Trouvez-la et desinstallez-la d’abord, ou attendez 5-10 minutes pour la propagation.
  • “Something went wrong” a l’upload : Uploadez via https://admin.teams.microsoft.com a la place, ouvrez les DevTools du navigateur (F12) → onglet Network, et verifiez le corps de la reponse pour l’erreur reelle.
  • Echec 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.

Permissions RSC non fonctionnelles

  1. Verifiez que webApplicationInfo.id correspond exactement a l’App ID de votre bot
  2. Re-uploadez l’application et reinstallez-la dans l’equipe/conversation
  3. Verifiez si l’administrateur de votre organisation a bloque les permissions RSC
  4. Confirmez que vous utilisez le bon scope : ChannelMessage.Read.Group pour les equipes, ChatMessage.Read.Chat pour les conversations de groupe

References