Zum Hauptinhalt springen

Microsoft Teams (Plugin)

„Lasst alle Hoffnung fahren, ihr, die ihr hier eintretet.“
Aktualisiert: 2026-01-21 Status: Text + DM-Anhänge werden unterstützt; Dateiübertragung in Kanälen/Gruppen erfordert sharePointSiteId + Graph-Berechtigungen (siehe Dateien in Gruppenchats senden). Umfragen werden über Adaptive Cards gesendet.

Erforderliches Plugin

Microsoft Teams wird als Plugin ausgeliefert und ist nicht im Core-Install enthalten. Breaking Change (2026.1.15): MS Teams wurde aus dem Core ausgelagert. Wenn Sie es verwenden, müssen Sie das Plugin installieren. Begründung: Hält Core-Installationen schlanker und ermöglicht unabhängige Updates der MS-Teams-Abhängigkeiten. Installation via CLI (npm-Registry):
openclaw plugins install @openclaw/msteams
Lokaler Checkout (bei Ausführung aus einem Git-Repo):
openclaw plugins install ./extensions/msteams
Wenn Sie Teams während Konfiguration/Onboarding auswählen und ein Git-Checkout erkannt wird, bietet OpenClaw den lokalen Installationspfad automatisch an. Details: Plugins

Schnellstart (Anfänger)

  1. Installieren Sie das Microsoft-Teams-Plugin.
  2. Erstellen Sie einen Azure Bot (App-ID + Client Secret + Tenant-ID).
  3. Konfigurieren Sie OpenClaw mit diesen Zugangsdaten.
  4. Exponieren Sie /api/messages (Standardport 3978) über eine öffentliche URL oder einen Tunnel.
  5. Installieren Sie das Teams-App-Paket und starten Sie 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, setzen Sie channels.msteams.groupAllowFrom (oder verwenden Sie groupPolicy: "open", um jedes Mitglied zuzulassen, erwähnungsbasiert).

Ziele

  • Mit OpenClaw über Teams-DMs, Gruppenchats oder Kanäle sprechen.
  • Deterministisches Routing beibehalten: Antworten gehen immer an den Kanal zurück, aus dem sie kamen.
  • Standardmäßig sicheres Kanalverhalten (Erwähnungen erforderlich, sofern nicht anders konfiguriert).

Konfigurationsschreibzugriffe

Standardmäßig darf Microsoft Teams Konfigurationsupdates schreiben, 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 genehmigt sind.
  • channels.msteams.allowFrom akzeptiert AAD-Objekt-IDs, UPNs oder Anzeigenamen. Der Assistent löst Namen bei ausreichenden Berechtigungen über Microsoft Graph in IDs auf.
Gruppenzugriff
  • Standard: channels.msteams.groupPolicy = "allowlist" (blockiert, sofern Sie nicht groupAllowFrom hinzufügen). Verwenden Sie channels.defaults.groupPolicy, um den Standard zu überschreiben, wenn nicht gesetzt.
  • channels.msteams.groupAllowFrom steuert, welche Absender in Gruppenchats/Kanälen auslösen dürfen (Fallback auf channels.msteams.allowFrom).
  • Setzen Sie groupPolicy: "open", um jedes Mitglied zuzulassen (standardmäßig weiterhin erwähnungsbasiert).
  • Um keine Kanäle zuzulassen, setzen Sie channels.msteams.groupPolicy: "disabled".
Beispiel:
{
  channels: {
    msteams: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["[email protected]"],
    },
  },
}
Teams- und Kanal-Allowlist
  • Begrenzen Sie Gruppen-/Kanalantworten, indem Sie Teams und Kanäle unter channels.msteams.teams auflisten.
  • Schlüssel können Team-IDs oder -Namen sein; Kanalschlüssel können Konversations-IDs oder -Namen sein.
  • Wenn groupPolicy="allowlist" gesetzt ist und eine Teams-Allowlist vorhanden ist, werden nur gelistete Teams/Kanäle akzeptiert (erwähnungsbasiert).
  • Der Konfigurationsassistent akzeptiert Team/Channel-Einträge und speichert sie für Sie.
  • Beim Start löst OpenClaw Team-/Kanal- und Benutzer-Allowlist-Namen in IDs auf (wenn Graph-Berechtigungen vorhanden sind) und protokolliert die Zuordnung; nicht auflösbare Einträge bleiben unverändert.
Beispiel:
{
  channels: {
    msteams: {
      groupPolicy: "allowlist",
      teams: {
        "My Team": {
          channels: {
            General: { requireMention: true },
          },
        },
      },
    },
  },
}

Wie es funktioniert

  1. Installieren Sie das Microsoft-Teams-Plugin.
  2. Erstellen Sie einen Azure Bot (App-ID + Secret + Tenant-ID).
  3. Erstellen Sie ein Teams-App-Paket, das auf den Bot verweist und die unten aufgeführten RSC-Berechtigungen enthält.
  4. Laden/installieren Sie die Teams-App in ein Team (oder im persönlichen Bereich für DMs).
  5. Konfigurieren Sie msteams in ~/.openclaw/openclaw.json (oder per Umgebungsvariablen) und starten Sie das Gateway.
  6. Das Gateway lauscht standardmäßig auf Bot-Framework-Webhook-Traffic unter /api/messages.

Azure Bot Setup (Voraussetzungen)

Bevor Sie OpenClaw konfigurieren, müssen Sie eine Azure-Bot-Ressource erstellen.

Schritt 1: Azure Bot erstellen

  1. Gehen Sie zu Azure Bot erstellen
  2. Füllen Sie den Reiter Basics aus:
    FeldWert
    Bot-NameIhr Botname, z. B. openclaw-msteams (muss eindeutig sein)
    AbonnementWählen Sie Ihr Azure-Abonnement
    RessourcengruppeNeu erstellen oder bestehende verwenden
    TarifstufeFree für Dev/Test
    App-TypSingle Tenant (empfohlen – siehe Hinweis unten)
    ErstellungstypNeue Microsoft App ID erstellen
Hinweis zur Abkündigung: Die Erstellung neuer Multi-Tenant-Bots wurde nach dem 2025-07-31 eingestellt. Verwenden Sie Single Tenant für neue Bots.
  1. Klicken Sie auf Review + createCreate (Wartezeit ~1–2 Minuten)

Schritt 2: Zugangsdaten abrufen

  1. Gehen Sie zu Ihrer Azure-Bot-Ressource → Configuration
  2. Kopieren Sie Microsoft App ID → das ist Ihre appId
  3. Klicken Sie auf Manage Password → zur App-Registrierung
  4. Unter Certificates & secretsNew client secret → kopieren Sie den Value → das ist Ihre appPassword
  5. Gehen Sie zu Overview → kopieren Sie Directory (tenant) ID → das ist Ihre tenantId

Schritt 3: Messaging Endpoint konfigurieren

  1. In Azure Bot → Konfiguration
  2. Setzen Sie Messaging endpoint auf Ihre Webhook-URL:
    • Produktion: https://your-domain.com/api/messages
    • Lokale Entwicklung: Verwenden Sie einen Tunnel (siehe Lokale Entwicklung unten)

Schritt 4: Teams-Kanal aktivieren

  1. In Azure Bot → Channels
  2. Klicken Sie auf Microsoft Teams → Configure → Save
  3. Akzeptieren Sie die Nutzungsbedingungen

Lokale Entwicklung (Tunneling)

Teams kann localhost nicht erreichen. Verwenden Sie für die lokale Entwicklung einen Tunnel: Option A: ngrok
ngrok http 3978
# Copy the https URL, e.g., https://abc123.ngrok.io
# Set messaging endpoint to: https://abc123.ngrok.io/api/messages
Option B: Tailscale Funnel
tailscale funnel 3978
# Use your Tailscale funnel URL as the messaging endpoint

Teams Developer Portal (Alternative)

Statt ein Manifest-ZIP manuell zu erstellen, können Sie das Teams Developer Portal verwenden:
  1. Klicken Sie auf + New app
  2. Füllen Sie die Basisinformationen aus (Name, Beschreibung, Entwicklerinfos)
  3. Gehen Sie zu App featuresBot
  4. Wählen Sie Enter a bot ID manually und fügen Sie Ihre Azure-Bot-App-ID ein
  5. Aktivieren Sie die Scopes: Personal, Team, Group Chat
  6. Klicken Sie auf DistributeDownload app package
  7. In Teams: AppsManage your appsUpload a custom app → ZIP auswählen
Dies ist oft einfacher als das manuelle Bearbeiten von JSON-Manifests.

Bot testen

Option A: Azure Web Chat (Webhook zuerst verifizieren)
  1. Im Azure-Portal → Ihre Azure-Bot-Ressource → Test in Web Chat
  2. Senden Sie eine Nachricht – Sie sollten eine Antwort sehen
  3. Dies bestätigt, dass Ihr Webhook-Endpunkt funktioniert, bevor Teams eingerichtet wird
Option B: Teams (nach App-Installation)
  1. Installieren Sie die Teams-App (Sideload oder Org-Katalog)
  2. Finden Sie den Bot in Teams und senden Sie eine DM
  3. Prüfen Sie die Gateway-Logs auf eingehende Aktivitäten

Setup (minimal, nur Text)

  1. Microsoft-Teams-Plugin installieren
    • Aus npm: openclaw plugins install @openclaw/msteams
    • Aus lokalem Checkout: openclaw plugins install ./extensions/msteams
  2. Bot-Registrierung
    • Erstellen Sie einen Azure Bot (siehe oben) und notieren Sie:
      • App-ID
      • Client Secret (App-Passwort)
      • Tenant-ID (Single Tenant)
  3. Teams-App-Manifest
    • Fügen Sie einen bot-Eintrag mit botId = <App ID> hinzu.
    • Scopes: personal, team, groupChat.
    • supportsFiles: true (erforderlich für Dateiverarbeitung im persönlichen Bereich).
    • RSC-Berechtigungen hinzufügen (siehe unten).
    • Icons erstellen: outline.png (32×32) und color.png (192×192).
    • Alle drei Dateien zusammen zippen: 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" }
      }
    }
    
    Sie können statt Konfigurationsschlüsseln auch Umgebungsvariablen verwenden:
    • MSTEAMS_APP_ID
    • MSTEAMS_APP_PASSWORD
    • MSTEAMS_TENANT_ID
  5. Bot-Endpunkt
    • Setzen Sie den Azure-Bot-Messaging-Endpunkt auf:
      • https://<host>:3978/api/messages (oder Ihren gewählten Pfad/Port).
  6. Gateway starten
    • Der Teams-Kanal startet automatisch, wenn das Plugin installiert ist und eine msteams-Konfiguration mit Zugangsdaten existiert.

Verlaufskontext

  • channels.msteams.historyLimit steuert, wie viele aktuelle Kanal-/Gruppennachrichten in den Prompt aufgenommen werden.
  • Fallback auf messages.groupChat.historyLimit. Setzen Sie 0, um zu deaktivieren (Standard 50).
  • DM-Verlauf kann mit channels.msteams.dmHistoryLimit (Benutzer-Turns) begrenzt werden. Pro-Benutzer-Overrides: channels.msteams.dms["<user_id>"].historyLimit.

Aktuelle Teams-RSC-Berechtigungen (Manifest)

Dies sind die vorhandenen resourceSpecific permissions in unserem Teams-App-Manifest. Sie gelten nur innerhalb des Teams/Chats, in dem die App installiert ist. Für Kanäle (Team-Scope):
  • ChannelMessage.Read.Group (Application) – alle Kanalnachrichten ohne @Erwähnung 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 Gruppenchats ohne @Erwähnung empfangen

Beispiel-Teams-Manifest (redigiert)

Minimales, gültiges Beispiel mit den erforderlichen Feldern. Ersetzen Sie 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-Hinweise (Pflichtfelder)

  • bots[].botId muss exakt der Azure-Bot-App-ID entsprechen.
  • webApplicationInfo.id muss der Azure-Bot-App-ID entsprechen.
  • bots[].scopes muss die von Ihnen geplanten Oberflächen enthalten (personal, team, groupChat).
  • bots[].supportsFiles: true ist für die Dateiverarbeitung im persönlichen Bereich erforderlich.
  • authorization.permissions.resourceSpecific muss Kanal-Lesen/Senden enthalten, wenn Sie Kanalverkehr möchten.

Aktualisieren einer bestehenden App

So aktualisieren Sie eine bereits installierte Teams-App (z. B. zum Hinzufügen von RSC-Berechtigungen):
  1. Aktualisieren Sie Ihr manifest.json mit den neuen Einstellungen
  2. Erhöhen Sie das Feld version (z. B. 1.0.01.1.0)
  3. Erneut zippen des Manifests mit Icons (manifest.json, outline.png, color.png)
  4. Neues ZIP hochladen:
    • Option A (Teams Admin Center): Teams Admin Center → Teams apps → Manage apps → App finden → Upload new version
    • Option B (Sideload): In Teams → Apps → Manage your apps → Upload a custom app
  5. Für Teamkanäle: App in jedem Team neu installieren, damit neue Berechtigungen wirksam werden
  6. Teams vollständig beenden und neu starten (nicht nur das Fenster schließen), um zwischengespeicherte Metadaten zu löschen

Fähigkeiten: Nur RSC vs. Graph

Mit Teams RSC בלבד (App installiert, keine Graph-API-Berechtigungen)

Funktioniert:
  • Lesen von Kanalnachrichten (Text).
  • Senden von Kanalnachrichten (Text).
  • Empfangen von persönlichen (DM) Dateianhängen.
Funktioniert NICHT:
  • Bild- oder Dateiinhalte in Kanälen/Gruppen (Payload enthält nur HTML-Stub).
  • Herunterladen von Anhängen aus SharePoint/OneDrive.
  • Lesen des Nachrichtenverlaufs (über das Live-Webhook-Ereignis hinaus).

Mit Teams RSC + Microsoft Graph Application-Berechtigungen

Zusätzlich:
  • Herunterladen gehosteter Inhalte (in Nachrichten eingefügte Bilder).
  • Herunterladen von Dateianhängen aus SharePoint/OneDrive.
  • Lesen des Kanal-/Chat-Nachrichtenverlaufs über Graph.

RSC vs. Graph API

FähigkeitRSC-BerechtigungenGraph API
EchtzeitnachrichtenJa (via Webhook)Nein (nur Polling)
Historische NachrichtenNeinJa (Verlauf abfragen)
Setup-KomplexitätNur App-ManifestErfordert Admin-Consent + Token-Flow
Offline nutzbarNein (muss laufen)Ja (jederzeit abfragen)
Fazit: RSC ist für Echtzeit-Zuhören; Graph API für historischen Zugriff. Um verpasste Nachrichten im Offline-Zustand nachzuholen, benötigen Sie die Graph API mit ChannelMessage.Read.All (erfordert Admin-Consent).

Graph-aktivierte Medien + Verlauf (erforderlich für Kanäle)

Wenn Sie Bilder/Dateien in Kanälen benötigen oder den Nachrichtenverlauf abrufen möchten, müssen Sie Microsoft-Graph-Berechtigungen aktivieren und Admin-Consent erteilen.
  1. In Entra ID (Azure AD) App Registration Microsoft Graph Application permissions hinzufügen:
    • ChannelMessage.Read.All (Kanalanhänge + Verlauf)
    • Chat.Read.All oder ChatMessage.Read.All (Gruppenchats)
  2. Admin-Consent für den Tenant erteilen.
  3. Teams-App-Manifest-Version erhöhen, erneut hochladen und App in Teams neu installieren.
  4. Teams vollständig beenden und neu starten, um Cache zu leeren.
Zusätzliche Berechtigung für Benutzererwähnungen: Benutzer-@mentions funktionieren standardmäßig für Benutzer in der Konversation. Wenn du jedoch Benutzer dynamisch suchen und erwähnen möchtest, die sich nicht in der aktuellen Konversation befinden, füge die Berechtigung User.Read.All (Application) hinzu und erteile Admin-Zustimmung.

Bekannte Einschränkungen

Webhook-Timeouts

Teams liefert Nachrichten per HTTP-Webhook. Wenn die Verarbeitung zu lange dauert (z. B. langsame LLM-Antworten), können auftreten:
  • Gateway-Timeouts
  • Teams wiederholt die Nachricht (verursacht Duplikate)
  • Verlorene Antworten
OpenClaw handhabt dies, indem es schnell zurückkehrt und Antworten proaktiv sendet; sehr langsame Antworten können dennoch Probleme verursachen.

Formatierung

Teams-Markdown ist eingeschränkter als Slack oder Discord:
  • Grundformatierung funktioniert: fett, kursiv, code, Links
  • Komplexes Markdown (Tabellen, verschachtelte Listen) wird möglicherweise nicht korrekt dargestellt
  • Adaptive Cards werden für Umfragen und beliebige Karten unterstützt (siehe unten)

Konfiguration

Wichtige Einstellungen (siehe /gateway/configuration für gemeinsame Kanal-Muster):
  • channels.msteams.enabled: Kanal 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 Assistent löst Namen bei verfügbarem Graph-Zugriff während des Setups in IDs auf.
  • channels.msteams.textChunkLimit: Ausgehende Text-Chunk-Größe.
  • channels.msteams.chunkMode: length (Standard) oder newline, um vor der Längenaufteilung an Leerzeilen (Absatzgrenzen) zu splitten.
  • channels.msteams.mediaAllowHosts: Allowlist für eingehende Anhang-Hosts (Standard: Microsoft-/Teams-Domains).
  • channels.msteams.mediaAuthAllowHosts: Allowlist zum Anhängen von Authorization-Headern bei Medien-Retries (Standard: Graph- + Bot-Framework-Hosts).
  • channels.msteams.requireMention: @Erwähnung in Kanälen/Gruppen erforderlich (Standard true).
  • channels.msteams.replyStyle: thread | top-level (siehe Antwortstil).
  • channels.msteams.teams.<teamId>.replyStyle: Pro-Team-Override.
  • channels.msteams.teams.<teamId>.requireMention: Pro-Team-Override.
  • channels.msteams.teams.<teamId>.tools: Standardmäßige Pro-Team-Werkzeugrichtlinien-Overrides (allow/deny/alsoAllow), die verwendet werden, wenn ein Kanal-Override fehlt.
  • channels.msteams.teams.<teamId>.toolsBySender: Standardmäßige Pro-Team-Pro-Absender-Werkzeugrichtlinien-Overrides ("*"-Wildcard unterstützt).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: Pro-Kanal-Override.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: Pro-Kanal-Override.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.tools: Pro-Kanal-Werkzeugrichtlinien-Overrides (allow/deny/alsoAllow).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: Pro-Kanal-Pro-Absender-Werkzeugrichtlinien-Overrides ("*"-Wildcard unterstützt).
  • channels.msteams.sharePointSiteId: SharePoint-Site-ID für Datei-Uploads in Gruppenchats/Kanälen (siehe Dateien in Gruppenchats senden).

Routing & Sitzungen

  • Sitzungsschlüssel folgen dem Standard-Agent-Format (siehe /concepts/session):
    • Direktnachrichten teilen sich die Hauptsitzung (agent:<agentId>:<mainKey>).
    • Kanal-/Gruppennachrichten verwenden die Konversations-ID:
      • agent:<agentId>:msteams:channel:<conversationId>
      • agent:<agentId>:msteams:group:<conversationId>

Antwortstil: Threads vs. Posts

Teams hat kürzlich zwei Kanal-UI-Stile über demselben zugrunde liegenden Datenmodell eingeführt:
StilBeschreibungEmpfohlenes replyStyle
Posts (klassisch)Nachrichten erscheinen als Karten mit Antworten darunterthread (Standard)
Threads (Slack-ähnlich)Nachrichten fließen linear, ähnlich wie Slacktop-level
Das Problem: Die Teams-API legt nicht offen, welchen UI-Stil ein Kanal verwendet. Wenn Sie das falsche replyStyle verwenden:
  • thread in einem Threads-Kanal → Antworten werden unglücklich verschachtelt angezeigt
  • top-level in einem Posts-Kanal → Antworten erscheinen als separate Top-Level-Posts statt im Thread
Lösung: Konfigurieren Sie replyStyle pro Kanal basierend auf der Kanaleinrichtung:
{
  "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 die Teams-Bot-Datei-APIs.
  • Kanäle/Gruppen: Anhänge liegen in M365-Speichern (SharePoint/OneDrive). Der Webhook-Payload enthält nur einen HTML-Stub, nicht die tatsächlichen Dateibytes. Graph-API-Berechtigungen sind erforderlich, um Kanalanhänge herunterzuladen.
Ohne Graph-Berechtigungen werden Kanalnachrichten mit Bildern nur als Text empfangen (der Bildinhalt ist für den Bot nicht zugänglich). Standardmäßig lädt OpenClaw Medien nur von Microsoft-/Teams-Hostnamen herunter. Überschreiben mit channels.msteams.mediaAllowHosts (verwenden Sie ["*"], um jeden Host zuzulassen). Authorization-Header werden nur für Hosts in channels.msteams.mediaAuthAllowHosts angehängt (Standard: Graph- + Bot-Framework-Hosts). Halten Sie diese Liste strikt (vermeiden Sie Multi-Tenant-Suffixe).

Dateien in Gruppenchats senden

Bots können Dateien in DMs über den FileConsentCard-Flow (integriert) senden. Das Senden von Dateien in Gruppenchats/Kanälen erfordert jedoch zusätzliche Einrichtung:
KontextWie Dateien gesendet werdenErforderliches Setup
DMsFileConsentCard → Nutzer akzeptiert → Bot lädt hochFunktioniert außerhalb der Box
Gruppenchats/KanäleUpload zu SharePoint → FreigabelinkErfordert sharePointSiteId + Graph-Berechtigungen
Bilder (jeder Kontext)Base64-kodiert inlineFunktioniert außerhalb der Box

Warum Gruppenchats SharePoint benötigen

Bots haben kein persönliches OneDrive-Laufwerk (der /me/drive-Graph-API-Endpunkt funktioniert nicht für Anwendungsidentitäten). Um Dateien in Gruppenchats/Kanälen zu senden, lädt der Bot in eine SharePoint-Site hoch und erstellt einen Freigabelink.

Setup

  1. Graph-API-Berechtigungen hinzufügen in Entra ID (Azure AD) → App Registration:
    • Sites.ReadWrite.All (Application) – Dateien zu SharePoint hochladen
    • Chat.Read.All (Application) – optional, ermöglicht benutzerspezifische Freigabelinks
  2. Admin-Consent für den Tenant erteilen.
  3. SharePoint-Site-ID ermitteln:
    # Via Graph Explorer or curl with a valid token:
    curl -H "Authorization: Bearer $TOKEN" \
      "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}"
    
    # Example: for a site at "contoso.sharepoint.com/sites/BotFiles"
    curl -H "Authorization: Bearer $TOKEN" \
      "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles"
    
    # Response includes: "id": "contoso.sharepoint.com,guid1,guid2"
    
  4. OpenClaw konfigurieren:
    {
      channels: {
        msteams: {
          // ... other config ...
          sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
        },
      },
    }
    

Freigabeverhalten

BerechtigungFreigabeverhalten
Sites.ReadWrite.All onlyOrganisationsweiter Freigabelink (alle im Org zugänglich)
Sites.ReadWrite.All + Chat.Read.AllBenutzerspezifischer Freigabelink (nur Chat-Mitglieder)
Benutzerspezifische Freigaben sind sicherer, da nur Chat-Teilnehmer Zugriff haben. Fehlt die Berechtigung Chat.Read.All, fällt der Bot auf organisationsweite Freigabe zurück.

Fallback-Verhalten

SzenarioErgebnis
Gruppenchats + Datei + sharePointSiteId konfiguriertUpload zu SharePoint, Freigabelink senden
Gruppenchats + Datei + kein sharePointSiteIdOneDrive-Upload versuchen (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-Dokumentbibliothek 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> ...
  • Stimmen werden vom Gateway in ~/.openclaw/msteams-polls.json gespeichert.
  • Das Gateway muss online bleiben, um Stimmen zu erfassen.
  • Umfragen posten derzeit noch keine Ergebniszusammenfassungen automatisch (prüfen Sie bei Bedarf die Store-Datei).

Adaptive Cards (beliebig)

Senden Sie beliebiges Adaptive-Card-JSON an Teams-Benutzer oder -Konversationen mit dem Werkzeug oder der CLI message. Der Parameter card akzeptiert ein Adaptive-Card-JSON-Objekt. Wenn card angegeben ist, ist der Nachrichtentext optional. Agent-Werkzeug:
{
  "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 Schema und Beispiele. Details zum Zielformat finden Sie unten unter Zielformate.

Zielformate

MSTeams-Ziele verwenden Präfixe zur Unterscheidung zwischen Benutzern und Konversationen:
ZieltypFormatBeispiel
Benutzer (nach ID)user:<aad-object-id>user:40a1a0ed-4ff2-4164-a219-55518990c197
Benutzer (nach Name)user:<display-name>user:John Smith (erfordert Graph API)
Gruppe/Kanalconversation:<conversation-id>conversation:19:[email protected]
Gruppe/Kanal (raw)<conversation-id>19:[email protected] (wenn @thread enthalten)
CLI-Beispiele:
# Send to a user by ID
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"

# Send to a user by display name (triggers Graph API lookup)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"

# Send to a group chat or channel
openclaw message send --channel msteams --target "conversation:19:[email protected]" --message "Hello"

# Send an Adaptive Card to a conversation
openclaw message send --channel msteams --target "conversation:19:[email protected]" \
  --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}'
Agent-Werkzeug-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 Präfix user: werden Namen standardmäßig als Gruppe/Team aufgelöst. Verwenden Sie immer user:, wenn Sie Personen nach Anzeigenamen ansprechen.

Proaktive Nachrichten

  • Proaktive Nachrichten sind nur nachdem ein Benutzer interagiert hat möglich, da wir zu diesem Zeitpunkt Konversationsreferenzen speichern.
  • Siehe /gateway/configuration für dmPolicy und Allowlist-Gating.

Team- und Kanal-IDs (häufige Stolperfalle)

Der Query-Parameter groupId in Teams-URLs ist NICHT die Team-ID, die für die Konfiguration verwendet wird. Extrahieren Sie stattdessen die IDs aus dem URL-Pfad: Team-URL:
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
                                    └────────────────────────────┘
                                    Team ID (URL-decode this)
Kanal-URL:
https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
                                      └─────────────────────────┘
                                      Channel ID (URL-decode this)
Für die Konfiguration:
  • Team-ID = Pfadsegment nach /team/ (URL-dekodiert, z. B. 19:[email protected])
  • Kanal-ID = Pfadsegment nach /channel/ (URL-dekodiert)
  • Ignorieren Sie den Query-Parameter groupId

Private Kanäle

Bots haben eingeschränkte Unterstützung in privaten Kanälen:
FunktionStandardkanälePrivate Kanäle
Bot-InstallationJaEingeschränkt
Echtzeitnachrichten (Webhook)JaFunktioniert sofort
RSC-BerechtigungenJaKönnen sich anders verhalten
@ErwähnungenJaWenn Bot zugänglich
Graph-API-VerlaufJaJa (mit Berechtigungen)
Workarounds, falls private Kanäle nicht funktionieren:
  1. Standardkanäle für Bot-Interaktionen verwenden
  2. DMs verwenden – Benutzer können den Bot jederzeit direkt anschreiben
  3. Graph API für historischen Zugriff verwenden (erfordert ChannelMessage.Read.All)

Häufige Probleme

Häufige Probleme

  • Bilder werden in Kanälen nicht angezeigt: Graph-Berechtigungen oder Admin-Consent fehlen. Teams-App neu installieren und Teams vollständig beenden/neu öffnen.
  • Keine Antworten im Kanal: Erwähnungen sind standardmäßig erforderlich; setzen Sie channels.msteams.requireMention=false oder konfigurieren Sie pro Team/Kanal.
  • Versionskonflikt (Teams zeigt noch altes Manifest): App entfernen + erneut hinzufügen und Teams vollständig beenden, um zu aktualisieren.
  • 401 Unauthorized vom Webhook: Erwartet bei manuellem Test ohne Azure-JWT – bedeutet, der Endpunkt ist erreichbar, aber die Authentifizierung schlug fehl. Verwenden Sie Azure Web Chat für korrekte Tests.

Fehler beim Manifest-Upload

  • „Icon file cannot be empty“: Das Manifest verweist auf Icon-Dateien mit 0 Byte. Erstellen Sie gültige PNG-Icons (32×32 für outline.png, 192×192 für color.png).
  • „webApplicationInfo.Id already in use“: Die App ist noch in einem anderen Team/Chat installiert. Deinstallieren Sie sie dort oder warten Sie 5–10 Minuten auf die Propagierung.
  • „Something went wrong“ beim Upload: Laden Sie stattdessen über https://admin.teams.microsoft.com hoch, öffnen Sie die Browser-DevTools (F12) → Network-Tab und prüfen Sie den Response-Body auf den eigentlichen Fehler.
  • Sideload schlägt fehl: Versuchen Sie „Upload an app to your org’s app catalog“ statt „Upload a custom app“ – das umgeht häufig Sideload-Beschränkungen.

RSC-Berechtigungen funktionieren nicht

  1. Verifizieren Sie, dass webApplicationInfo.id exakt der App-ID Ihres Bots entspricht
  2. App erneut hochladen und im Team/Chat neu installieren
  3. Prüfen Sie, ob Ihr Org-Admin RSC-Berechtigungen blockiert hat
  4. Bestätigen Sie den richtigen Scope: ChannelMessage.Read.Group für Teams, ChatMessage.Read.Chat für Gruppenchats

Referenzen