Microsoft Teams (Plugin)

“Abandon all hope, ye who enter here.”

Aktualisiert: 21.01.2026

Status: Text + DM-Anhänge werden unterstützt; das Senden von Dateien in Channels/Gruppen erfordert sharePointSiteId + Graph-Berechtigungen (siehe Dateien in Gruppenchats senden). Umfragen werden über Adaptive Cards gesendet.

Plugin erforderlich

Microsoft Teams wird als Plugin ausgeliefert und ist nicht im Core-Install enthalten.

Breaking Change (15.01.2026): MS Teams wurde aus dem Core entfernt. Wenn du es nutzt, musst du das Plugin installieren.

Begründung: Hält Core-Installationen schlanker und ermöglicht unabhängige Updates der MS Teams-Abhängigkeiten.

Installation über CLI (npm Registry):

openclaw plugins install @openclaw/msteams

Lokaler Checkout (beim Ausführen aus einem Git-Repo):

openclaw plugins install ./extensions/msteams

Wenn du Teams während der Konfiguration/Onboarding auswählst und ein Git-Checkout erkannt wird, bietet OpenClaw automatisch den lokalen Installationspfad an.

Details: Plugins

Schnellstart (Einsteiger)

  1. Installiere das Microsoft Teams Plugin.
  2. Erstelle einen Azure Bot (App ID + Client Secret + Tenant ID).
  3. Konfiguriere OpenClaw mit diesen Zugangsdaten.
  4. Stelle /api/messages (standardmäßig Port 3978) über eine öffentliche URL oder einen Tunnel bereit.
  5. Installiere das Teams-App-Paket und starte das Gateway.

Minimale Konfiguration:

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

Hinweis: Gruppenchats sind standardmäßig blockiert (channels.msteams.groupPolicy: "allowlist"). Um Gruppenantworten zu erlauben, setze channels.msteams.groupAllowFrom (oder nutze groupPolicy: "open", um alle Mitglieder zuzulassen, Mention-gated).

Ziele

  • Mit OpenClaw über Teams-DMs, Gruppenchats oder Channels kommunizieren.
  • Routing deterministisch halten: Antworten gehen immer zurück zum Channel, von dem sie kamen.
  • Standardmäßig sicheres Channel-Verhalten (Mentions erforderlich, sofern nicht anders konfiguriert).

Config-Schreibzugriff

Standardmäßig darf Microsoft Teams Config-Updates durchführen, die durch /config set|unset ausgelöst werden (erfordert commands.config: true).

Deaktivieren mit:

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

Zugriffskontrolle (DMs + Gruppen)

DM-Zugriff

  • Standard: channels.msteams.dmPolicy = "pairing". Unbekannte Absender werden ignoriert, bis sie freigegeben werden.
  • channels.msteams.allowFrom akzeptiert AAD-Objekt-IDs, UPNs oder Anzeigenamen. Der Wizard löst Namen zu IDs über Microsoft Graph auf, wenn die Zugangsdaten es erlauben.

Gruppenzugriff

  • Standard: channels.msteams.groupPolicy = "allowlist" (blockiert, bis du groupAllowFrom hinzufügst). Nutze channels.defaults.groupPolicy, um den Standard zu überschreiben, wenn nicht gesetzt.
  • channels.msteams.groupAllowFrom steuert, welche Absender in Gruppenchats/Channels auslösen können (fällt zurück auf channels.msteams.allowFrom).
  • Setze groupPolicy: "open", um alle Mitglieder zuzulassen (standardmäßig weiterhin Mention-gated).
  • Um keine Channels zuzulassen, setze channels.msteams.groupPolicy: "disabled".

Beispiel:

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

Teams + Channel Allowlist

  • Begrenze Gruppen-/Channel-Antworten, indem du Teams und Channels unter channels.msteams.teams auflistest.
  • Schlüssel können Team-IDs oder Namen sein; Channel-Schlüssel können Conversation-IDs oder Namen sein.
  • Wenn groupPolicy="allowlist" und eine Teams-Allowlist vorhanden ist, werden nur aufgelistete Teams/Channels akzeptiert (Mention-gated).
  • Der Konfigurations-Wizard akzeptiert Team/Channel-Einträge und speichert sie für dich.
  • Beim Start löst OpenClaw Team-/Channel- und User-Allowlist-Namen zu IDs auf (wenn Graph-Berechtigungen vorhanden sind) und loggt das Mapping; nicht aufgelöste Einträge werden wie eingegeben beibehalten.

Beispiel:

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

So funktioniert es

  1. Installiere das Microsoft Teams Plugin.
  2. Erstelle einen Azure Bot (App ID + Secret + Tenant ID).
  3. Erstelle ein Teams-App-Paket, das den Bot referenziert und die RSC-Berechtigungen unten enthält.
  4. Lade die Teams-App in ein Team hoch/installiere sie (oder im persönlichen Bereich für DMs).
  5. Konfiguriere msteams in ~/.openclaw/openclaw.json (oder Umgebungsvariablen) und starte das Gateway.
  6. Das Gateway lauscht standardmäßig auf Bot Framework Webhook-Traffic auf /api/messages.

Azure Bot Setup (Voraussetzungen)

Bevor du OpenClaw konfigurierst, musst du eine Azure Bot-Ressource erstellen.

Schritt 1: Azure Bot erstellen

  1. Gehe zu Azure Bot erstellen

  2. Fülle den Basics-Tab aus:

    FeldWert
    Bot handleDein Bot-Name, z. B. openclaw-msteams (muss eindeutig sein)
    SubscriptionWähle dein Azure-Abonnement
    Resource groupNeu erstellen oder vorhandene verwenden
    Pricing tierFree für Dev/Testing
    Type of AppSingle Tenant (empfohlen - siehe Hinweis unten)
    Creation typeCreate new Microsoft App ID

Deprecation-Hinweis: Die Erstellung neuer Multi-Tenant-Bots wurde nach dem 31.07.2025 eingestellt. Nutze Single Tenant für neue Bots.

  1. Klicke auf Review + createCreate (warte ca. 1-2 Minuten)

Schritt 2: Zugangsdaten abrufen

  1. Gehe zu deiner Azure Bot-Ressource → Configuration
  2. Kopiere Microsoft App ID → das ist deine appId
  3. Klicke auf Manage Password → gehe zur App Registration
  4. Unter Certificates & secretsNew client secret → kopiere den Value → das ist dein appPassword
  5. Gehe zu Overview → kopiere Directory (tenant) ID → das ist deine tenantId

Schritt 3: Messaging Endpoint konfigurieren

  1. In Azure Bot → Configuration
  2. Setze Messaging endpoint auf deine Webhook-URL:
    • Produktion: https://your-domain.com/api/messages
    • Lokale Entwicklung: Nutze einen Tunnel (siehe Lokale Entwicklung unten)

Schritt 4: Teams Channel aktivieren

  1. In Azure Bot → Channels
  2. Klicke auf Microsoft Teams → Configure → Save
  3. Akzeptiere die Nutzungsbedingungen

Lokale Entwicklung (Tunneling)

Teams kann localhost nicht erreichen. Nutze einen Tunnel für die lokale Entwicklung:

Option A: ngrok

ngrok http 3978
# Kopiere die HTTPS-URL, z. B. https://abc123.ngrok.io
# Setze Messaging Endpoint auf: https://abc123.ngrok.io/api/messages

Option B: Tailscale Funnel

tailscale funnel 3978
# Nutze deine Tailscale Funnel-URL als Messaging Endpoint

Teams Developer Portal (Alternative)

Anstatt manuell ein Manifest-ZIP zu erstellen, kannst du das Teams Developer Portal nutzen:

  1. Klicke auf + New app
  2. Fülle die Basisinformationen aus (Name, Beschreibung, Entwicklerinfo)
  3. Gehe zu App featuresBot
  4. Wähle Enter a bot ID manually und füge deine Azure Bot App ID ein
  5. Aktiviere Scopes: Personal, Team, Group Chat
  6. Klicke auf DistributeDownload app package
  7. In Teams: AppsManage your appsUpload a custom app → wähle das ZIP

Das ist oft einfacher als das manuelle Bearbeiten von JSON-Manifesten.

Bot testen

Option A: Azure Web Chat (Webhook zuerst verifizieren)

  1. Im Azure Portal → deine Azure Bot-Ressource → Test in Web Chat
  2. Sende eine Nachricht - du solltest eine Antwort sehen
  3. Das bestätigt, dass dein Webhook-Endpoint funktioniert, bevor du Teams einrichtest

Option B: Teams (nach App-Installation)

  1. Installiere die Teams-App (Sideload oder Org-Katalog)
  2. Finde den Bot in Teams und sende eine DM
  3. Prüfe die Gateway-Logs auf eingehende Aktivität

Setup (minimal, nur Text)

  1. Installiere das Microsoft Teams Plugin

    • Von npm: openclaw plugins install @openclaw/msteams
    • Von einem lokalen Checkout: openclaw plugins install ./extensions/msteams
  2. Bot-Registrierung

    • Erstelle einen Azure Bot (siehe oben) und notiere:
      • App ID
      • Client Secret (App-Passwort)
      • Tenant ID (Single-Tenant)
  3. Teams-App-Manifest

    • Füge einen bot-Eintrag mit botId = <App ID> hinzu.
    • Scopes: personal, team, groupChat.
    • supportsFiles: true (erforderlich für Dateihandling im persönlichen Bereich).
    • Füge RSC-Berechtigungen hinzu (unten).
    • Erstelle Icons: outline.png (32x32) und color.png (192x192).
    • Zippe alle drei Dateien zusammen: manifest.json, outline.png, color.png.
  4. OpenClaw konfigurieren

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

    Du kannst auch Umgebungsvariablen anstelle von Config-Keys verwenden:

    • MSTEAMS_APP_ID
    • MSTEAMS_APP_PASSWORD
    • MSTEAMS_TENANT_ID
  5. Bot-Endpoint

    • Setze den Azure Bot Messaging Endpoint auf:
      • https://<host>:3978/api/messages (oder deinen gewählten Pfad/Port).
  6. Gateway starten

    • Der Teams-Channel startet automatisch, wenn das Plugin installiert ist und eine msteams-Config mit Zugangsdaten existiert.

History Context

  • channels.msteams.historyLimit steuert, wie viele aktuelle Channel-/Gruppennachrichten in den Prompt eingebunden werden.
  • Fällt zurück auf messages.groupChat.historyLimit. Setze 0 zum Deaktivieren (Standard 50).
  • DM-History kann mit channels.msteams.dmHistoryLimit (User-Turns) begrenzt werden. Pro-User-Overrides: channels.msteams.dms["<user_id>"].historyLimit.

Aktuelle Teams RSC-Berechtigungen (Manifest)

Das sind die vorhandenen resourceSpecific-Berechtigungen in unserem Teams-App-Manifest. Sie gelten nur innerhalb des Teams/Chats, in dem die App installiert ist.

Für Channels (Team-Scope):

  • ChannelMessage.Read.Group (Application) - alle Channel-Nachrichten ohne @mention empfangen
  • ChannelMessage.Send.Group (Application)
  • Member.Read.Group (Application)
  • Owner.Read.Group (Application)
  • ChannelSettings.Read.Group (Application)
  • TeamMember.Read.Group (Application)
  • TeamSettings.Read.Group (Application)

Für Gruppenchats:

  • ChatMessage.Read.Chat (Application) - alle Gruppenchat-Nachrichten ohne @mention empfangen

Beispiel Teams-Manifest (gekürzt)

Minimales, gültiges Beispiel mit den erforderlichen Feldern. Ersetze IDs und 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" }
      ]
    }
  }
}

Manifest-Fallstricke (Pflichtfelder)

  • bots[].botId muss mit der Azure Bot App ID übereinstimmen.
  • webApplicationInfo.id muss mit der Azure Bot App ID übereinstimmen.
  • bots[].scopes muss die Oberflächen enthalten, die du nutzen möchtest (personal, team, groupChat).
  • bots[].supportsFiles: true ist erforderlich für Dateihandling im persönlichen Bereich.
  • authorization.permissions.resourceSpecific muss Channel-Read/Send enthalten, wenn du Channel-Traffic möchtest.

Vorhandene App aktualisieren

Um eine bereits installierte Teams-App zu aktualisieren (z. B. um RSC-Berechtigungen hinzuzufügen):

  1. Aktualisiere dein manifest.json mit den neuen Einstellungen
  2. Erhöhe das version-Feld (z. B. 1.0.01.1.0)
  3. Zippe neu das Manifest mit Icons (manifest.json, outline.png, color.png)
  4. Lade das neue ZIP hoch:
    • Option A (Teams Admin Center): Teams Admin Center → Teams apps → Manage apps → finde deine App → Upload new version
    • Option B (Sideload): In Teams → Apps → Manage your apps → Upload a custom app
  5. Für Team-Channels: Installiere die App in jedem Team neu, damit neue Berechtigungen wirksam werden
  6. Beende Teams vollständig und starte neu (nicht nur Fenster schließen), um gecachte App-Metadaten zu löschen

Funktionen: Nur RSC vs. Graph

Mit nur Teams RSC (App installiert, keine Graph API-Berechtigungen)

Funktioniert:

  • Channel-Nachrichten als Text lesen.
  • Channel-Nachrichten als Text senden.
  • Persönliche (DM) Dateianhänge empfangen.

Funktioniert NICHT:

  • Channel-/Gruppen-Bilder oder Dateiinhalte (Payload enthält nur HTML-Stub).
  • Anhänge herunterladen, die in SharePoint/OneDrive gespeichert sind.
  • Nachrichtenverlauf lesen (über das Live-Webhook-Event hinaus).

Mit Teams RSC + Microsoft Graph Application-Berechtigungen

Zusätzlich:

  • Gehostete Inhalte herunterladen (Bilder, die in Nachrichten eingefügt wurden).
  • Dateianhänge herunterladen, die in SharePoint/OneDrive gespeichert sind.
  • Channel-/Chat-Nachrichtenverlauf über Graph lesen.

RSC vs. Graph API

FunktionRSC-BerechtigungenGraph API
Echtzeit-NachrichtenJa (via Webhook)Nein (nur Polling)
Historische NachrichtenNeinJa (kann Verlauf abfragen)
Setup-KomplexitätNur App-ManifestErfordert Admin-Consent + Token-Flow
Funktioniert offlineNein (muss laufen)Ja (jederzeit abfragen)

Fazit: RSC ist für Echtzeit-Listening; Graph API ist für historischen Zugriff. Um verpasste Nachrichten nachzuholen, während du offline warst, brauchst du Graph API mit ChannelMessage.Read.All (erfordert Admin-Consent).

Graph-aktivierte Medien + Verlauf (erforderlich für Channels)

Wenn du Bilder/Dateien in Channels brauchst oder Nachrichtenverlauf abrufen möchtest, musst du Microsoft Graph-Berechtigungen aktivieren und Admin-Consent erteilen.

  1. In Entra ID (Azure AD) App Registration, füge Microsoft Graph Application-Berechtigungen hinzu:
    • ChannelMessage.Read.All (Channel-Anhänge + Verlauf)
    • Chat.Read.All oder ChatMessage.Read.All (Gruppenchats)
  2. Erteile Admin-Consent für den Tenant.
  3. Erhöhe die Teams-App Manifest-Version, lade sie neu hoch und installiere die App in Teams neu.
  4. Beende Teams vollständig und starte neu, um gecachte App-Metadaten zu löschen.

Bekannte Einschränkungen

Webhook-Timeouts

Teams liefert Nachrichten über HTTP-Webhook. Wenn die Verarbeitung zu lange dauert (z. B. langsame LLM-Antworten), kannst du Folgendes sehen:

  • Gateway-Timeouts
  • Teams wiederholt die Nachricht (verursacht Duplikate)
  • Verlorene Antworten

OpenClaw behandelt dies, indem es schnell zurückkehrt und Antworten proaktiv sendet, aber sehr langsame Antworten können weiterhin Probleme verursachen.

Formatierung

Teams-Markdown ist eingeschränkter als Slack oder Discord:

  • Grundlegende Formatierung funktioniert: fett, kursiv, code, Links
  • Komplexes Markdown (Tabellen, verschachtelte Listen) wird möglicherweise nicht korrekt gerendert
  • Adaptive Cards werden für Umfragen und beliebige Card-Sends unterstützt (siehe unten)

Konfiguration

Wichtige Einstellungen (siehe /gateway/configuration für gemeinsame Channel-Muster):

  • channels.msteams.enabled: Channel aktivieren/deaktivieren.
  • channels.msteams.appId, channels.msteams.appPassword, channels.msteams.tenantId: Bot-Zugangsdaten.
  • channels.msteams.webhook.port (Standard 3978)
  • channels.msteams.webhook.path (Standard /api/messages)
  • channels.msteams.dmPolicy: pairing | allowlist | open | disabled (Standard: pairing)
  • channels.msteams.allowFrom: Allowlist für DMs (AAD-Objekt-IDs, UPNs oder Anzeigenamen). Der Wizard löst Namen zu IDs während des Setups auf, wenn Graph-Zugriff verfügbar ist.
  • channels.msteams.textChunkLimit: Ausgehende Text-Chunk-Größe.
  • channels.msteams.chunkMode: length (Standard) oder newline, um bei Leerzeilen (Absatzgrenzen) vor dem Length-Chunking zu splitten.
  • channels.msteams.mediaAllowHosts: Allowlist für eingehende Anhang-Hosts (Standard: Microsoft/Teams-Domains).
  • channels.msteams.requireMention: @mention in Channels/Gruppen erforderlich (Standard true).
  • channels.msteams.replyStyle: thread | top-level (siehe Reply Style).
  • channels.msteams.teams.<teamId>.replyStyle: Pro-Team-Override.
  • channels.msteams.teams.<teamId>.requireMention: Pro-Team-Override.
  • channels.msteams.teams.<teamId>.tools: Standard-Pro-Team-Tool-Policy-Overrides (allow/deny/alsoAllow), die verwendet werden, wenn ein Channel-Override fehlt.
  • channels.msteams.teams.<teamId>.toolsBySender: Standard-Pro-Team-Pro-Sender-Tool-Policy-Overrides ("*" Wildcard unterstützt).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: Pro-Channel-Override.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: Pro-Channel-Override.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.tools: Pro-Channel-Tool-Policy-Overrides (allow/deny/alsoAllow).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: Pro-Channel-Pro-Sender-Tool-Policy-Overrides ("*" Wildcard unterstützt).
  • channels.msteams.sharePointSiteId: SharePoint-Site-ID für Datei-Uploads in Gruppenchats/Channels (siehe Dateien in Gruppenchats senden).

Routing & Sessions

  • Session-Keys folgen dem Standard-Agent-Format (siehe /concepts/session):
    • Direktnachrichten teilen die Main-Session (agent:<agentId>:<mainKey>).
    • Channel-/Gruppennachrichten nutzen Conversation-ID:
      • agent:<agentId>:msteams:channel:<conversationId>
      • agent:<agentId>:msteams:group:<conversationId>

Reply Style: Threads vs Posts

Teams hat kürzlich zwei Channel-UI-Stile über dasselbe zugrunde liegende Datenmodell eingeführt:

StilBeschreibungEmpfohlener replyStyle
Posts (klassisch)Nachrichten erscheinen als Karten mit Thread-Antworten darunterthread (Standard)
Threads (Slack-ähnlich)Nachrichten fließen linear, mehr wie Slacktop-level

Das Problem: Die Teams-API zeigt nicht, welchen UI-Stil ein Channel nutzt. Wenn du den falschen replyStyle verwendest:

  • thread in einem Threads-Style-Channel → Antworten erscheinen unpassend verschachtelt
  • top-level in einem Posts-Style-Channel → Antworten erscheinen als separate Top-Level-Posts statt im Thread

Lösung: Konfiguriere replyStyle pro Channel basierend darauf, wie der Channel eingerichtet ist:

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

Anhänge & Bilder

Aktuelle Einschränkungen:

  • DMs: Bilder und Dateianhänge funktionieren über Teams Bot File APIs.
  • Channels/Gruppen: Anhänge liegen in M365-Storage (SharePoint/OneDrive). Die Webhook-Payload enthält nur einen HTML-Stub, nicht die tatsächlichen Datei-Bytes. Graph API-Berechtigungen sind erforderlich, um Channel-Anhänge herunterzuladen.

Ohne Graph-Berechtigungen werden Channel-Nachrichten mit Bildern nur als Text empfangen (der Bildinhalt ist für den Bot nicht zugänglich). Standardmäßig lädt OpenClaw nur Medien von Microsoft/Teams-Hostnamen herunter. Override mit channels.msteams.mediaAllowHosts (nutze ["*"], um jeden Host zu erlauben).

Dateien in Gruppenchats senden

Bots können Dateien in DMs über den FileConsentCard-Flow senden (eingebaut). Jedoch erfordert das Senden von Dateien in Gruppenchats/Channels zusätzliches Setup:

KontextWie Dateien gesendet werdenSetup benötigt
DMsFileConsentCard → User akzeptiert → Bot lädt hochFunktioniert out of the box
Gruppenchats/ChannelsUpload zu SharePoint → Sharing-Link teilenErfordert sharePointSiteId + Graph-Berechtigungen
Bilder (jeder Kontext)Base64-kodiert inlineFunktioniert out of the box

Warum Gruppenchats SharePoint brauchen

Bots haben kein persönliches OneDrive-Laufwerk (der /me/drive Graph API-Endpoint funktioniert nicht für Application-Identitäten). Um Dateien in Gruppenchats/Channels zu senden, lädt der Bot zu einer SharePoint-Site hoch und erstellt einen Sharing-Link.

Setup

  1. Füge Graph API-Berechtigungen hinzu in Entra ID (Azure AD) → App Registration:

    • Sites.ReadWrite.All (Application) - Dateien zu SharePoint hochladen
    • Chat.Read.All (Application) - optional, ermöglicht Pro-User-Sharing-Links
  2. Erteile Admin-Consent für den Tenant.

  3. Hole deine SharePoint-Site-ID:

    # Via Graph Explorer oder curl mit einem gültigen Token:
    curl -H "Authorization: Bearer $TOKEN" \
      "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}"
    
    # Beispiel: für eine Site bei "contoso.sharepoint.com/sites/BotFiles"
    curl -H "Authorization: Bearer $TOKEN" \
      "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles"
    
    # Response enthält: "id": "contoso.sharepoint.com,guid1,guid2"
  4. Konfiguriere OpenClaw:

    {
      channels: {
        msteams: {
          // ... andere Config ...
          sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
        },
      },
    }

Sharing-Verhalten

BerechtigungSharing-Verhalten
Nur Sites.ReadWrite.AllOrganisationsweiter Sharing-Link (jeder in der Org kann zugreifen)
Sites.ReadWrite.All + Chat.Read.AllPro-User-Sharing-Link (nur Chat-Mitglieder können zugreifen)

Pro-User-Sharing ist sicherer, da nur die Chat-Teilnehmer auf die Datei zugreifen können. Wenn die Chat.Read.All-Berechtigung fehlt, fällt der Bot auf organisationsweites Sharing zurück.

Fallback-Verhalten

SzenarioErgebnis
Gruppenchat + Datei + sharePointSiteId konfiguriertUpload zu SharePoint, Sharing-Link senden
Gruppenchat + Datei + kein sharePointSiteIdVersuch OneDrive-Upload (kann fehlschlagen), nur Text senden
Persönlicher Chat + DateiFileConsentCard-Flow (funktioniert ohne SharePoint)
Jeder Kontext + BildBase64-kodiert inline (funktioniert ohne SharePoint)

Speicherort der Dateien

Hochgeladene Dateien werden in einem /OpenClawShared/-Ordner in der Standard-Dokumentenbibliothek der konfigurierten SharePoint-Site gespeichert.

Umfragen (Adaptive Cards)

OpenClaw sendet Teams-Umfragen als Adaptive Cards (es gibt keine native Teams-Umfrage-API).

  • CLI: openclaw message poll --channel msteams --target conversation:<id> ...
  • Votes werden vom Gateway in ~/.openclaw/msteams-polls.json aufgezeichnet.
  • Das Gateway muss online bleiben, um Votes aufzuzeichnen.
  • Umfragen posten noch keine automatischen Ergebnis-Zusammenfassungen (prüfe die Store-Datei bei Bedarf).

Adaptive Cards (beliebig)

Sende beliebige Adaptive Card JSON an Teams-User oder Conversations mit dem message-Tool oder CLI.

Der card-Parameter akzeptiert ein Adaptive Card JSON-Objekt. Wenn card angegeben ist, ist der Nachrichtentext optional.

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

Siehe Adaptive Cards-Dokumentation für Card-Schema und Beispiele. Für Target-Format-Details siehe Target-Formate unten.

Target-Formate

MSTeams-Targets nutzen Präfixe, um zwischen Usern und Conversations zu unterscheiden:

Target-TypFormatBeispiel
User (nach ID)user:<aad-object-id>user:40a1a0ed-4ff2-4164-a219-55518990c197
User (nach Name)user:<display-name>user:John Smith (erfordert Graph API)
Gruppe/Channelconversation:<conversation-id>conversation:19:[email protected]
Gruppe/Channel (raw)<conversation-id>19:[email protected] (wenn @thread enthält)

CLI-Beispiele:

# An einen User nach ID senden
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"

# An einen User nach Anzeigename senden (löst Graph API-Lookup aus)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"

# An einen Gruppenchat oder Channel senden
openclaw message send --channel msteams --target "conversation:19:[email protected]" --message "Hello"

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

Agent-Tool-Beispiele:

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

Hinweis: Ohne das user:-Präfix werden Namen standardmäßig als Gruppen-/Team-Auflösung behandelt. Nutze immer user:, wenn du Personen nach Anzeigename ansprichst.

Proaktive Nachrichten

  • Proaktive Nachrichten sind nur nach einer User-Interaktion möglich, weil wir zu diesem Zeitpunkt Conversation-Referenzen speichern.
  • Siehe /gateway/configuration für dmPolicy und Allowlist-Gating.

Team- und Channel-IDs (Häufiger Fehler)

Der groupId-Query-Parameter in Teams-URLs ist NICHT die Team-ID, die für die Konfiguration verwendet wird. Extrahiere IDs stattdessen aus dem URL-Pfad:

Team-URL:

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

Channel-URL:

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

Für die Config:

  • Team-ID = Pfad-Segment nach /team/ (URL-dekodiert, z. B. 19:[email protected])
  • Channel-ID = Pfad-Segment nach /channel/ (URL-dekodiert)
  • Ignoriere den groupId-Query-Parameter

Private Channels

Bots haben eingeschränkte Unterstützung in privaten Channels:

FeatureStandard-ChannelsPrivate Channels
Bot-InstallationJaEingeschränkt
Echtzeit-Nachrichten (Webhook)JaFunktioniert möglicherweise nicht
RSC-BerechtigungenJaVerhalten kann abweichen
@mentionsJaWenn Bot zugänglich ist
Graph API-VerlaufJaJa (mit Berechtigungen)

Workarounds, wenn private Channels nicht funktionieren:

  1. Nutze Standard-Channels für Bot-Interaktionen
  2. Nutze DMs - User können den Bot immer direkt anschreiben
  3. Nutze Graph API für historischen Zugriff (erfordert ChannelMessage.Read.All)

Troubleshooting

Häufige Probleme

  • Bilder werden in Channels nicht angezeigt: Graph-Berechtigungen oder Admin-Consent fehlen. Installiere die Teams-App neu und beende/öffne Teams vollständig.
  • Keine Antworten im Channel: Mentions sind standardmäßig erforderlich; setze channels.msteams.requireMention=false oder konfiguriere pro Team/Channel.
  • Versions-Mismatch (Teams zeigt noch altes Manifest): Entferne + füge die App neu hinzu und beende Teams vollständig, um zu aktualisieren.
  • 401 Unauthorized vom Webhook: Erwartet beim manuellen Testen ohne Azure JWT - bedeutet, dass der Endpoint erreichbar ist, aber Auth fehlgeschlagen ist. Nutze Azure Web Chat zum korrekten Testen.

Manifest-Upload-Fehler

  • “Icon file cannot be empty”: Das Manifest referenziert Icon-Dateien, die 0 Bytes groß sind. Erstelle gültige PNG-Icons (32x32 für outline.png, 192x192 für color.png).
  • “webApplicationInfo.Id already in use”: Die App ist noch in einem anderen Team/Chat installiert. Finde und deinstalliere sie zuerst, oder warte 5-10 Minuten auf Propagierung.
  • “Something went wrong” beim Upload: Lade über https://admin.teams.microsoft.com hoch, öffne Browser DevTools (F12) → Network-Tab und prüfe den Response-Body für den tatsächlichen Fehler.
  • Sideload schlägt fehl: Versuche “Upload an app to your org’s app catalog” statt “Upload a custom app” - das umgeht oft Sideload-Beschränkungen.

RSC-Berechtigungen funktionieren nicht

  1. Verifiziere, dass webApplicationInfo.id exakt mit deiner Bot-App-ID übereinstimmt
  2. Lade die App neu hoch und installiere sie im Team/Chat neu
  3. Prüfe, ob dein Org-Admin RSC-Berechtigungen blockiert hat
  4. Bestätige, dass du den richtigen Scope nutzt: ChannelMessage.Read.Group für Teams, ChatMessage.Read.Chat für Gruppenchats

Referenzen