Microsoft Teams (plugin)

“Abandon all hope, ye who enter here.”

Bijgewerkt: 2026-01-21

Status: tekst + DM-bijlagen worden ondersteund; kanaal-/groepsbestandverzending vereist sharePointSiteId + Graph-machtigingen (zie Bestanden versturen in groepschats). Polls worden verstuurd via Adaptive Cards.

Plugin vereist

Microsoft Teams wordt als plugin geleverd en is niet gebundeld met de kerninstallatie.

Breaking change (2026.1.15): MS Teams is uit de kern verplaatst. Als je het gebruikt, moet je de plugin installeren.

Uitleg: houdt kerninstallaties lichter en laat MS Teams-afhankelijkheden onafhankelijk updaten.

Installeren via CLI (npm-register):

openclaw plugins install @openclaw/msteams

Lokale checkout (bij draaien vanuit een git-repo):

openclaw plugins install ./extensions/msteams

Als je Teams kiest tijdens configureren/onboarding en een git-checkout wordt gedetecteerd, biedt OpenClaw automatisch het lokale installatiepad aan.

Details: Plugins

Snelle installatie (beginner)

  1. Installeer de Microsoft Teams-plugin.
  2. Maak een Azure Bot aan (App ID + client secret + tenant ID).
  3. Configureer OpenClaw met die credentials.
  4. Stel /api/messages beschikbaar (standaard poort 3978) via een publieke URL of tunnel.
  5. Installeer het Teams-app-pakket en start de gateway.

Minimale configuratie:

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

Opmerking: groepschats worden standaard geblokkeerd (channels.msteams.groupPolicy: "allowlist"). Om groepsantwoorden toe te staan, stel channels.msteams.groupAllowFrom in (of gebruik groupPolicy: "open" om elk lid toe te staan, vermelding-beveiligd).

Doelen

  • Praat met OpenClaw via Teams-DM’s, groepschats of kanalen.
  • Houd routering deterministisch: antwoorden gaan altijd terug naar het kanaal waar ze vandaan kwamen.
  • Standaard veilig kanaalgedrag (vermeldingen vereist tenzij anders geconfigureerd).

Configschrijfacties

Standaard mag Microsoft Teams config-updates schrijven die worden getriggerd door /config set|unset (vereist commands.config: true).

Uitschakelen met:

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

Toegangscontrole (DM’s + groepen)

DM-toegang

  • Standaard: channels.msteams.dmPolicy = "pairing". Onbekende afzenders worden genegeerd totdat goedgekeurd.
  • channels.msteams.allowFrom moet stabiele AAD-object-ID’s gebruiken.
  • UPN’s/weergavenamen zijn veranderlijk; directe matching is standaard uitgeschakeld en wordt alleen ingeschakeld met channels.msteams.dangerouslyAllowNameMatching: true.
  • De wizard kan namen oplossen naar ID’s via Microsoft Graph wanneer credentials dit toelaten.

Groepstoegang

  • Standaard: channels.msteams.groupPolicy = "allowlist" (geblokkeerd tenzij je groupAllowFrom toevoegt). Gebruik channels.defaults.groupPolicy om de standaard te overschrijven wanneer niet ingesteld.
  • channels.msteams.groupAllowFrom bepaalt welke afzenders in groepschats/kanalen kunnen triggeren (valt terug op channels.msteams.allowFrom).
  • Stel groupPolicy: "open" in om elk lid toe te staan (nog steeds standaard vermelding-beveiligd).
  • Om geen kanalen toe te staan, stel channels.msteams.groupPolicy: "disabled" in.

Voorbeeld:

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

Teams + kanaal-allowlist

  • Beperk groeps-/kanaalantwoorden door teams en kanalen onder channels.msteams.teams te vermelden.
  • Sleutels moeten stabiele team-ID’s en kanaalconversatie-ID’s gebruiken.
  • Wanneer groupPolicy="allowlist" en een teams-allowlist aanwezig is, worden alleen vermelde teams/kanalen geaccepteerd (vermelding-beveiligd).
  • De configuratiewizard accepteert Team/Channel-vermeldingen en slaat ze voor je op.
  • Bij opstart lost OpenClaw team-/kanaal- en gebruiker-allowlistnamen op naar ID’s (wanneer Graph-machtigingen dit toelaten) en logt de mapping; niet-opgeloste team-/kanaalnamen worden bewaard zoals getypt maar standaard genegeerd voor routering tenzij channels.msteams.dangerouslyAllowNameMatching: true is ingeschakeld.

Voorbeeld:

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

Hoe het werkt

  1. Installeer de Microsoft Teams-plugin.
  2. Maak een Azure Bot aan (App ID + secret + tenant ID).
  3. Bouw een Teams-app-pakket dat de bot referenceert en de onderstaande RSC-machtigingen bevat.
  4. Upload/installeer de Teams-app in een team (of persoonlijk bereik voor DM’s).
  5. Configureer msteams in ~/.openclaw/openclaw.json (of env-variabelen) en start de gateway.
  6. De gateway luistert standaard naar Bot Framework-webhookverkeer op /api/messages.

Azure Bot-installatie (vereisten)

Voordat je OpenClaw configureert, moet je een Azure Bot-resource aanmaken.

Stap 1: Azure Bot aanmaken

  1. Ga naar Create Azure Bot

  2. Vul het tabblad Basics in:

    VeldWaarde
    Bot handleJe botnaam, bijv. openclaw-msteams (moet uniek zijn)
    SubscriptionSelecteer je Azure-abonnement
    Resource groupMaak nieuw aan of gebruik bestaand
    Pricing tierFree voor dev/testen
    Type of AppSingle Tenant (aanbevolen - zie opmerking hieronder)
    Creation typeCreate new Microsoft App ID

Opmerking: Het aanmaken van nieuwe multi-tenant-bots is verouderd na 2025-07-31. Gebruik Single Tenant voor nieuwe bots.

  1. Klik op Review + createCreate (wacht ~1-2 minuten)

Stap 2: Credentials ophalen

  1. Ga naar je Azure Bot-resource → Configuration
  2. Kopieer Microsoft App ID → dit is je appId
  3. Klik op Manage Password → ga naar de App Registration
  4. Onder Certificates & secretsNew client secret → kopieer de Value → dit is je appPassword
  5. Ga naar Overview → kopieer Directory (tenant) ID → dit is je tenantId

Stap 3: Berichteindpunt configureren

  1. In Azure Bot → Configuration
  2. Stel Messaging endpoint in op je webhook-URL:
    • Productie: https://your-domain.com/api/messages
    • Lokale ontwikkeling: gebruik een tunnel (zie Lokale ontwikkeling hieronder)

Stap 4: Teams-kanaal inschakelen

  1. In Azure Bot → Channels
  2. Klik op Microsoft Teams → Configure → Save
  3. Accepteer de servicevoorwaarden

Lokale ontwikkeling (tunneling)

Teams kan localhost niet bereiken. Gebruik een tunnel voor lokale ontwikkeling:

Optie A: ngrok

ngrok http 3978
# Kopieer de https-URL, bijv. https://abc123.ngrok.io
# Stel het berichteindpunt in op: https://abc123.ngrok.io/api/messages

Optie B: Tailscale Funnel

tailscale funnel 3978
# Gebruik je Tailscale-funnel-URL als berichteindpunt

Teams Developer Portal (alternatief)

In plaats van handmatig een manifest-ZIP te maken, kun je het Teams Developer Portal gebruiken:

  1. Klik op + New app
  2. Vul basisinformatie in (naam, beschrijving, ontwikkelaarsinformatie)
  3. Ga naar App featuresBot
  4. Selecteer Enter a bot ID manually en plak je Azure Bot App ID
  5. Vink scopes aan: Personal, Team, Group Chat
  6. Klik op DistributeDownload app package
  7. In Teams: AppsManage your appsUpload a custom app → selecteer de ZIP

Dit is vaak makkelijker dan het handmatig bewerken van JSON-manifesten.

De bot testen

Optie A: Azure Web Chat (webhook eerst verifiëren)

  1. In Azure Portal → je Azure Bot-resource → Test in Web Chat
  2. Stuur een bericht — je zou een antwoord moeten zien
  3. Dit bevestigt dat je webhook-eindpunt werkt vóór de Teams-setup

Optie B: Teams (na app-installatie)

  1. Installeer de Teams-app (sideload of orgcatalogus)
  2. Zoek de bot in Teams en stuur een DM
  3. Controleer gatewaylogs op inkomende activiteit

Setup (minimaal, alleen tekst)

  1. Installeer de Microsoft Teams-plugin

    • Vanuit npm: openclaw plugins install @openclaw/msteams
    • Vanuit een lokale checkout: openclaw plugins install ./extensions/msteams
  2. Botregistratie

    • Maak een Azure Bot aan (zie hierboven) en noteer:
      • App ID
      • Client secret (app-wachtwoord)
      • Tenant ID (single-tenant)
  3. Teams-app-manifest

    • Voeg een bot-vermelding toe met botId = <App ID>.
    • Scopes: personal, team, groupChat.
    • supportsFiles: true (vereist voor bestandsafhandeling in persoonlijk bereik).
    • Voeg RSC-machtigingen toe (hieronder).
    • Maak iconen: outline.png (32x32) en color.png (192x192).
    • Zip alle drie bestanden samen: manifest.json, outline.png, color.png.
  4. Configureer OpenClaw

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

    Je kunt ook omgevingsvariabelen gebruiken in plaats van configuratiesleutels:

    • MSTEAMS_APP_ID
    • MSTEAMS_APP_PASSWORD
    • MSTEAMS_TENANT_ID
  5. Bot-eindpunt

    • Stel het Azure Bot-berichteindpunt in op:
      • https://<host>:3978/api/messages (of je gekozen pad/poort).
  6. Start de gateway

    • Het Teams-kanaal start automatisch wanneer de plugin is geïnstalleerd en msteams-configuratie bestaat met credentials.

Geschiedeniscontext

  • channels.msteams.historyLimit bepaalt hoeveel recente kanaal-/groepsberichten in de prompt worden opgenomen.
  • Valt terug op messages.groupChat.historyLimit. Stel 0 in om uit te schakelen (standaard 50).
  • DM-geschiedenis kan worden beperkt met channels.msteams.dmHistoryLimit (gebruikersbeurten). Per-gebruiker-overschrijvingen: channels.msteams.dms["<user_id>"].historyLimit.

Huidige Teams RSC-machtigingen (manifest)

Dit zijn de bestaande resourceSpecific-machtigingen in ons Teams-app-manifest. Ze gelden alleen binnen het team/de chat waar de app is geïnstalleerd.

Voor kanalen (teambereik):

  • ChannelMessage.Read.Group (Application) - alle kanaalberichten ontvangen zonder @vermelding
  • ChannelMessage.Send.Group (Application)
  • Member.Read.Group (Application)
  • Owner.Read.Group (Application)
  • ChannelSettings.Read.Group (Application)
  • TeamMember.Read.Group (Application)
  • TeamSettings.Read.Group (Application)

Voor groepschats:

  • ChatMessage.Read.Chat (Application) - alle groepschatberichten ontvangen zonder @vermelding

Voorbeeld Teams-manifest (geanonimiseerd)

Minimaal, geldig voorbeeld met de vereiste velden. Vervang ID’s en URL’s.

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

Manifestwaarschuwingen (verplichte velden)

  • bots[].botId moet overeenkomen met de Azure Bot App ID.
  • webApplicationInfo.id moet overeenkomen met de Azure Bot App ID.
  • bots[].scopes moet de oppervlakken bevatten die je wilt gebruiken (personal, team, groupChat).
  • bots[].supportsFiles: true is vereist voor bestandsafhandeling in persoonlijk bereik.
  • authorization.permissions.resourceSpecific moet kanaal-lees/verstuur bevatten als je kanaalverkeer wilt.

Een bestaande app bijwerken

Om een reeds geïnstalleerde Teams-app bij te werken (bijv. om RSC-machtigingen toe te voegen):

  1. Werk je manifest.json bij met de nieuwe instellingen
  2. Verhoog het version-veld (bijv. 1.0.01.1.0)
  3. Zip opnieuw het manifest met iconen (manifest.json, outline.png, color.png)
  4. Upload de nieuwe zip:
    • Optie A (Teams Admin Center): Teams Admin Center → Teams apps → Manage apps → zoek je app → Upload new version
    • Optie B (Sideload): In Teams → Apps → Manage your apps → Upload a custom app
  5. Voor teamkanalen: herinstalleer de app in elk team zodat nieuwe machtigingen van kracht worden
  6. Sluit Teams volledig af en herstart (niet alleen het venster sluiten) om gecachete app-metadata te wissen

Mogelijkheden: alleen RSC vs Graph

Met alleen Teams RSC (app geïnstalleerd, geen Graph API-machtigingen)

Werkt:

  • Kanaalberichten tekstinhoud lezen.
  • Kanaalberichten tekstinhoud versturen.
  • Persoonlijke (DM) bestandsbijlagen ontvangen.

Werkt NIET:

  • Kanaal-/groeps-afbeelding- of bestandsinhoud (payload bevat alleen HTML-stub).
  • Bijlagen downloaden die zijn opgeslagen in SharePoint/OneDrive.
  • Berichtgeschiedenis lezen (buiten het live webhook-event).

Met Teams RSC + Microsoft Graph-applicatiemachtigingen

Voegt toe:

  • Gehoste inhoud downloaden (afbeeldingen geplakt in berichten).
  • Bestandsbijlagen downloaden die zijn opgeslagen in SharePoint/OneDrive.
  • Kanaal-/chatberichtgeschiedenis lezen via Graph.

RSC vs Graph API

MogelijkheidRSC-machtigingenGraph API
Realtime berichtenJa (via webhook)Nee (alleen polling)
Historische berichtenNeeJa (kan geschiedenis opvragen)
SetupcomplexiteitAlleen app-manifestVereist admin-toestemming + tokenflow
Werkt offlineNee (moet draaien)Ja (altijd opvraagbaar)

Conclusie: RSC is voor realtime luisteren; Graph API is voor historische toegang. Om gemiste berichten in te halen terwijl je offline was, heb je Graph API nodig met ChannelMessage.Read.All (vereist admin-toestemming).

Graph-enabled media + geschiedenis (vereist voor kanalen)

Als je afbeeldingen/bestanden nodig hebt in kanalen of berichtgeschiedenis wilt ophalen, moet je Microsoft Graph-machtigingen inschakelen en admin-toestemming verlenen.

  1. Voeg in Entra ID (Azure AD) App Registration Microsoft Graph applicatiemachtigingen toe:
    • ChannelMessage.Read.All (kanaalbijlagen + geschiedenis)
    • Chat.Read.All of ChatMessage.Read.All (groepschats)
  2. Verleen admin-toestemming voor de tenant.
  3. Verhoog de Teams-app-manifestversie, upload opnieuw en herinstalleer de app in Teams.
  4. Sluit Teams volledig af en herstart om gecachete app-metadata te wissen.

Extra machtiging voor gebruikersvermeldingen: Gebruikers-@vermeldingen werken direct voor gebruikers in het gesprek. Als je echter dynamisch gebruikers wilt zoeken en vermelden die niet in het huidige gesprek zitten, voeg dan User.Read.All (Application) machtiging toe en verleen admin-toestemming.

Bekende beperkingen

Webhook-timeouts

Teams levert berichten af via HTTP-webhook. Als verwerking te lang duurt (bijv. trage LLM-antwoorden), kun je het volgende zien:

  • Gateway-timeouts
  • Teams probeert het bericht opnieuw (veroorzaakt duplicaten)
  • Verloren antwoorden

OpenClaw handelt dit af door snel te antwoorden en proactief antwoorden te versturen, maar zeer trage antwoorden kunnen nog steeds problemen veroorzaken.

Opmaak

Teams-markdown is beperkter dan Slack of Discord:

  • Basisopmaak werkt: vet, cursief, code, links
  • Complexe markdown (tabellen, geneste lijsten) kan niet correct worden weergegeven
  • Adaptive Cards worden ondersteund voor polls en willekeurige kaartverzendingen (zie hieronder)

Configuratie

Belangrijke instellingen (zie /gateway/configuration voor gedeelde kanaalpatronen):

  • channels.msteams.enabled: kanaal in-/uitschakelen.
  • channels.msteams.appId, channels.msteams.appPassword, channels.msteams.tenantId: botcredentials.
  • channels.msteams.webhook.port (standaard 3978)
  • channels.msteams.webhook.path (standaard /api/messages)
  • channels.msteams.dmPolicy: pairing | allowlist | open | disabled (standaard: pairing)
  • channels.msteams.allowFrom: DM-allowlist (AAD-object-ID’s aanbevolen). De wizard lost namen op naar ID’s tijdens setup wanneer Graph-toegang beschikbaar is.
  • channels.msteams.dangerouslyAllowNameMatching: noodschakelaar om veranderlijke UPN-/weergavenaammatching en directe team-/kanaalnaamroutering opnieuw in te schakelen.
  • channels.msteams.textChunkLimit: uitgaande tekstchunkgrootte.
  • channels.msteams.chunkMode: length (standaard) of newline om te splitsen op lege regels (alineagrenzen) voor lengteopsplitsing.
  • channels.msteams.mediaAllowHosts: allowlist voor inkomende bijlage-hosts (standaard Microsoft/Teams-domeinen).
  • channels.msteams.mediaAuthAllowHosts: allowlist voor het toevoegen van Authorization-headers bij mediapogingen (standaard Graph + Bot Framework-hosts).
  • channels.msteams.requireMention: @vermelding vereisen in kanalen/groepen (standaard true).
  • channels.msteams.replyStyle: thread | top-level (zie Antwoordstijl).
  • channels.msteams.teams.<teamId>.replyStyle: per-team-overschrijving.
  • channels.msteams.teams.<teamId>.requireMention: per-team-overschrijving.
  • channels.msteams.teams.<teamId>.tools: standaard per-team-toolbeleidsoverschrijvingen (allow/deny/alsoAllow) gebruikt wanneer een kanaaloverschrijving ontbreekt.
  • channels.msteams.teams.<teamId>.toolsBySender: standaard per-team per-afzender toolbeleidsoverschrijvingen ("*" wildcard ondersteund).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: per-kanaal-overschrijving.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: per-kanaal-overschrijving.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.tools: per-kanaal toolbeleidsoverschrijvingen (allow/deny/alsoAllow).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: per-kanaal per-afzender toolbeleidsoverschrijvingen ("*" wildcard ondersteund).
  • toolsBySender-sleutels moeten expliciete prefixen gebruiken: id:, e164:, username:, name: (verouderde niet-geprefixte sleutels mappen nog steeds naar alleen id:).
  • channels.msteams.sharePointSiteId: SharePoint-site-ID voor bestanduploads in groepschats/kanalen (zie Bestanden versturen in groepschats).

Routering en sessies

  • Sessiesleutels volgen het standaard agentformaat (zie /concepts/session):
    • Directe berichten delen de hoofdsessie (agent:<agentId>:<mainKey>).
    • Kanaal-/groepsberichten gebruiken conversatie-ID:
      • agent:<agentId>:msteams:channel:<conversationId>
      • agent:<agentId>:msteams:group:<conversationId>

Antwoordstijl: threads vs posts

Teams heeft onlangs twee kanaal-UI-stijlen geïntroduceerd bovenop hetzelfde onderliggende datamodel:

StijlBeschrijvingAanbevolen replyStyle
Posts (klassiek)Berichten verschijnen als kaarten met threaded antwoorden eronderthread (standaard)
Threads (Slack-achtig)Berichten stromen lineair, meer zoals Slacktop-level

Het probleem: De Teams API stelt niet bloot welke UI-stijl een kanaal gebruikt. Als je de verkeerde replyStyle gebruikt:

  • thread in een Threads-stijlkanaal → antwoorden verschijnen onhandig genest
  • top-level in een Posts-stijlkanaal → antwoorden verschijnen als aparte top-level posts in plaats van in-thread

Oplossing: Configureer replyStyle per kanaal op basis van hoe het kanaal is ingesteld:

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

Bijlagen en afbeeldingen

Huidige beperkingen:

  • DM’s: Afbeeldingen en bestandsbijlagen werken via Teams bot-bestands-API’s.
  • Kanalen/groepen: Bijlagen bevinden zich in M365-opslag (SharePoint/OneDrive). De webhookpayload bevat alleen een HTML-stub, niet de daadwerkelijke bestandsbytes. Graph API-machtigingen zijn vereist om kanaalbijlagen te downloaden.

Zonder Graph-machtigingen worden kanaalberichten met afbeeldingen ontvangen als alleen-tekst (de afbeeldingsinhoud is niet toegankelijk voor de bot). Standaard downloadt OpenClaw alleen media van Microsoft/Teams-hostnamen. Overschrijf met channels.msteams.mediaAllowHosts (gebruik ["*"] om elke host toe te staan). Authorization-headers worden alleen toegevoegd voor hosts in channels.msteams.mediaAuthAllowHosts (standaard Graph + Bot Framework-hosts). Houd deze lijst strikt (vermijd multi-tenant-suffixen).

Bestanden versturen in groepschats

Bots kunnen bestanden versturen in DM’s met de FileConsentCard-flow (ingebouwd). Echter, bestanden versturen in groepschats/kanalen vereist extra setup:

ContextHoe bestanden worden verstuurdBenodigde setup
DM’sFileConsentCard → gebruiker accepteert → bot uploadtWerkt direct
Groepschats/kanalenUploaden naar SharePoint → deellink versturenVereist sharePointSiteId + Graph-machtigingen
Afbeeldingen (elke context)Base64-gecodeerd inlineWerkt direct

Waarom groepschats SharePoint nodig hebben

Bots hebben geen persoonlijk OneDrive-station (het /me/drive Graph API-eindpunt werkt niet voor applicatie-identiteiten). Om bestanden te versturen in groepschats/kanalen uploadt de bot naar een SharePoint-site en maakt een deellink aan.

Setup

  1. Voeg Graph API-machtigingen toe in Entra ID (Azure AD) → App Registration:

    • Sites.ReadWrite.All (Application) - bestanden uploaden naar SharePoint
    • Chat.Read.All (Application) - optioneel, maakt per-gebruiker deellinks mogelijk
  2. Verleen admin-toestemming voor de tenant.

  3. Verkrijg je SharePoint-site-ID:

    # Via Graph Explorer of curl met een geldig token:
    curl -H "Authorization: Bearer $TOKEN" \
      "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}"
    
    # Voorbeeld: voor een site op "contoso.sharepoint.com/sites/BotFiles"
    curl -H "Authorization: Bearer $TOKEN" \
      "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles"
    
    # Antwoord bevat: "id": "contoso.sharepoint.com,guid1,guid2"
  4. Configureer OpenClaw:

    {
      channels: {
        msteams: {
          // ... overige configuratie ...
          sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
        },
      },
    }

Deelgedrag

MachtigingDeelgedrag
Alleen Sites.ReadWrite.AllOrganisatiebrede deellink (iedereen in de organisatie kan toegang krijgen)
Sites.ReadWrite.All + Chat.Read.AllPer-gebruiker deellink (alleen chatleden kunnen toegang krijgen)

Per-gebruiker delen is veiliger omdat alleen de chatdeelnemers toegang hebben tot het bestand. Als de Chat.Read.All-machtiging ontbreekt, valt de bot terug op organisatiebrede deling.

Terugvalgedrag

ScenarioResultaat
Groepschat + bestand + sharePointSiteId geconfigureerdUploaden naar SharePoint, deellink versturen
Groepschat + bestand + geen sharePointSiteIdPoging OneDrive-upload (kan falen), alleen tekst versturen
Persoonlijke chat + bestandFileConsentCard-flow (werkt zonder SharePoint)
Elke context + afbeeldingBase64-gecodeerd inline (werkt zonder SharePoint)

Opslaglocatie bestanden

Geüploade bestanden worden opgeslagen in een /OpenClawShared/-map in de standaard documentbibliotheek van de geconfigureerde SharePoint-site.

Polls (Adaptive Cards)

OpenClaw verstuurt Teams-polls als Adaptive Cards (er is geen native Teams-poll-API).

  • CLI: openclaw message poll --channel msteams --target conversation:<id> ...
  • Stemmen worden geregistreerd door de gateway in ~/.openclaw/msteams-polls.json.
  • De gateway moet online blijven om stemmen te registreren.
  • Polls posten nog geen automatische resultaatsamenvattingen (inspecteer het opslagbestand indien nodig).

Adaptive Cards (willekeurig)

Verstuur elke Adaptive Card JSON naar Teams-gebruikers of -gesprekken met de message-tool of CLI.

De card-parameter accepteert een Adaptive Card JSON-object. Wanneer card is opgegeven, is de berichttekst optioneel.

Agent-tool:

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

Zie Adaptive Cards-documentatie voor kaartschema en voorbeelden. Voor doelformaatdetails, zie Doelformaten hieronder.

Doelformaten

MSTeams-doelen gebruiken prefixen om onderscheid te maken tussen gebruikers en gesprekken:

DoeltypeFormaatVoorbeeld
Gebruiker (op ID)user:<aad-object-id>user:40a1a0ed-4ff2-4164-a219-55518990c197
Gebruiker (op naam)user:<display-name>user:John Smith (vereist Graph API)
Groep/kanaalconversation:<conversation-id>conversation:19:[email protected]
Groep/kanaal (raw)<conversation-id>19:[email protected] (als het @thread bevat)

CLI-voorbeelden:

# Verstuur naar een gebruiker op ID
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"

# Verstuur naar een gebruiker op weergavenaam (triggert Graph API-lookup)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"

# Verstuur naar een groepschat of kanaal
openclaw message send --channel msteams --target "conversation:19:[email protected]" --message "Hello"

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

Agent-tool-voorbeelden:

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

Opmerking: zonder het user:-prefix worden namen standaard naar groeps-/teamresolutie geleid. Gebruik altijd user: bij het targeten van mensen op weergavenaam.

Proactieve berichten

  • Proactieve berichten zijn alleen mogelijk nadat een gebruiker heeft geïnteracteerd, omdat we op dat moment gespreksreferenties opslaan.
  • Zie /gateway/configuration voor dmPolicy en allowlist-gating.

Team- en kanaal-ID’s (veelgemaakte fout)

De groupId-queryparameter in Teams-URL’s is NIET de team-ID die wordt gebruikt voor configuratie. Haal ID’s uit het URL-pad:

Team-URL:

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

Kanaal-URL:

https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
                                      └─────────────────────────┘
                                      Kanaal-ID (URL-decodeer dit)

Voor configuratie:

  • Team-ID = padsegment na /team/ (URL-gedecodeerd, bijv. 19:[email protected])
  • Kanaal-ID = padsegment na /channel/ (URL-gedecodeerd)
  • Negeer de groupId-queryparameter

Privékanalen

Bots hebben beperkte ondersteuning in privékanalen:

FunctieStandaardkanalenPrivékanalen
BotinstallatieJaBeperkt
Realtime berichten (webhook)JaWerkt mogelijk niet
RSC-machtigingenJaKan anders werken
@vermeldingenJaAls bot toegankelijk is
Graph API-geschiedenisJaJa (met machtigingen)

Workarounds als privékanalen niet werken:

  1. Gebruik standaardkanalen voor botinteracties
  2. Gebruik DM’s — gebruikers kunnen de bot altijd direct berichten
  3. Gebruik Graph API voor historische toegang (vereist ChannelMessage.Read.All)

Probleemoplossing

Veelvoorkomende problemen

  • Afbeeldingen worden niet getoond in kanalen: Graph-machtigingen of admin-toestemming ontbreekt. Herinstalleer de Teams-app en sluit Teams volledig af/heropen.
  • Geen antwoorden in kanaal: vermeldingen zijn standaard vereist; stel channels.msteams.requireMention=false in of configureer per team/kanaal.
  • Versiemismatch (Teams toont nog oud manifest): verwijder + voeg de app opnieuw toe en sluit Teams volledig af om te vernieuwen.
  • 401 Unauthorized van webhook: verwacht bij handmatig testen zonder Azure JWT — betekent dat het eindpunt bereikbaar is maar auth mislukte. Gebruik Azure Web Chat om correct te testen.

Manifest-uploadfouten

  • “Icon file cannot be empty”: Het manifest verwijst naar icoonbestanden van 0 bytes. Maak geldige PNG-iconen (32x32 voor outline.png, 192x192 voor color.png).
  • “webApplicationInfo.Id already in use”: De app is nog geïnstalleerd in een ander team/chat. Zoek en deïnstalleer deze eerst, of wacht 5-10 minuten op propagatie.
  • “Something went wrong” bij upload: Upload via https://admin.teams.microsoft.com in plaats daarvan, open browser DevTools (F12) → Network-tabblad, en controleer de response-body op de werkelijke fout.
  • Sideload mislukt: Probeer “Upload an app to your org’s app catalog” in plaats van “Upload a custom app” — dit omzeilt vaak sideload-restricties.

RSC-machtigingen werken niet

  1. Verifieer dat webApplicationInfo.id exact overeenkomt met de App ID van je bot
  2. Upload de app opnieuw en herinstalleer in het team/de chat
  3. Controleer of je organisatiebeheerder RSC-machtigingen heeft geblokkeerd
  4. Bevestig dat je het juiste bereik gebruikt: ChannelMessage.Read.Group voor teams, ChatMessage.Read.Chat voor groepschats

Referenties