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)
- Installiere das Microsoft Teams Plugin.
- Erstelle einen Azure Bot (App ID + Client Secret + Tenant ID).
- Konfiguriere OpenClaw mit diesen Zugangsdaten.
- Stelle
/api/messages(standardmäßig Port 3978) über eine öffentliche URL oder einen Tunnel bereit. - 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.allowFromakzeptiert 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 dugroupAllowFromhinzufügst). Nutzechannels.defaults.groupPolicy, um den Standard zu überschreiben, wenn nicht gesetzt. channels.msteams.groupAllowFromsteuert, welche Absender in Gruppenchats/Channels auslösen können (fällt zurück aufchannels.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.teamsauflistest. - 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
- Installiere das Microsoft Teams Plugin.
- Erstelle einen Azure Bot (App ID + Secret + Tenant ID).
- Erstelle ein Teams-App-Paket, das den Bot referenziert und die RSC-Berechtigungen unten enthält.
- Lade die Teams-App in ein Team hoch/installiere sie (oder im persönlichen Bereich für DMs).
- Konfiguriere
msteamsin~/.openclaw/openclaw.json(oder Umgebungsvariablen) und starte das Gateway. - 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
-
Gehe zu Azure Bot erstellen
-
Fülle den Basics-Tab aus:
Feld Wert Bot handle Dein Bot-Name, z. B. openclaw-msteams(muss eindeutig sein)Subscription Wähle dein Azure-Abonnement Resource group Neu erstellen oder vorhandene verwenden Pricing tier Free für Dev/Testing Type of App Single Tenant (empfohlen - siehe Hinweis unten) Creation type Create 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.
- Klicke auf Review + create → Create (warte ca. 1-2 Minuten)
Schritt 2: Zugangsdaten abrufen
- Gehe zu deiner Azure Bot-Ressource → Configuration
- Kopiere Microsoft App ID → das ist deine
appId - Klicke auf Manage Password → gehe zur App Registration
- Unter Certificates & secrets → New client secret → kopiere den Value → das ist dein
appPassword - Gehe zu Overview → kopiere Directory (tenant) ID → das ist deine
tenantId
Schritt 3: Messaging Endpoint konfigurieren
- In Azure Bot → Configuration
- Setze Messaging endpoint auf deine Webhook-URL:
- Produktion:
https://your-domain.com/api/messages - Lokale Entwicklung: Nutze einen Tunnel (siehe Lokale Entwicklung unten)
- Produktion:
Schritt 4: Teams Channel aktivieren
- In Azure Bot → Channels
- Klicke auf Microsoft Teams → Configure → Save
- 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:
- Klicke auf + New app
- Fülle die Basisinformationen aus (Name, Beschreibung, Entwicklerinfo)
- Gehe zu App features → Bot
- Wähle Enter a bot ID manually und füge deine Azure Bot App ID ein
- Aktiviere Scopes: Personal, Team, Group Chat
- Klicke auf Distribute → Download app package
- In Teams: Apps → Manage your apps → Upload 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)
- Im Azure Portal → deine Azure Bot-Ressource → Test in Web Chat
- Sende eine Nachricht - du solltest eine Antwort sehen
- Das bestätigt, dass dein Webhook-Endpoint funktioniert, bevor du Teams einrichtest
Option B: Teams (nach App-Installation)
- Installiere die Teams-App (Sideload oder Org-Katalog)
- Finde den Bot in Teams und sende eine DM
- Prüfe die Gateway-Logs auf eingehende Aktivität
Setup (minimal, nur Text)
-
Installiere das Microsoft Teams Plugin
- Von npm:
openclaw plugins install @openclaw/msteams - Von einem lokalen Checkout:
openclaw plugins install ./extensions/msteams
- Von npm:
-
Bot-Registrierung
- Erstelle einen Azure Bot (siehe oben) und notiere:
- App ID
- Client Secret (App-Passwort)
- Tenant ID (Single-Tenant)
- Erstelle einen Azure Bot (siehe oben) und notiere:
-
Teams-App-Manifest
- Füge einen
bot-Eintrag mitbotId = <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) undcolor.png(192x192). - Zippe alle drei Dateien zusammen:
manifest.json,outline.png,color.png.
- Füge einen
-
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_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
-
Bot-Endpoint
- Setze den Azure Bot Messaging Endpoint auf:
https://<host>:3978/api/messages(oder deinen gewählten Pfad/Port).
- Setze den Azure Bot Messaging Endpoint auf:
-
Gateway starten
- Der Teams-Channel startet automatisch, wenn das Plugin installiert ist und eine
msteams-Config mit Zugangsdaten existiert.
- Der Teams-Channel startet automatisch, wenn das Plugin installiert ist und eine
History Context
channels.msteams.historyLimitsteuert, wie viele aktuelle Channel-/Gruppennachrichten in den Prompt eingebunden werden.- Fällt zurück auf
messages.groupChat.historyLimit. Setze0zum 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 empfangenChannelMessage.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[].botIdmuss mit der Azure Bot App ID übereinstimmen.webApplicationInfo.idmuss mit der Azure Bot App ID übereinstimmen.bots[].scopesmuss die Oberflächen enthalten, die du nutzen möchtest (personal,team,groupChat).bots[].supportsFiles: trueist erforderlich für Dateihandling im persönlichen Bereich.authorization.permissions.resourceSpecificmuss 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):
- Aktualisiere dein
manifest.jsonmit den neuen Einstellungen - Erhöhe das
version-Feld (z. B.1.0.0→1.1.0) - Zippe neu das Manifest mit Icons (
manifest.json,outline.png,color.png) - 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
- Für Team-Channels: Installiere die App in jedem Team neu, damit neue Berechtigungen wirksam werden
- 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
| Funktion | RSC-Berechtigungen | Graph API |
|---|---|---|
| Echtzeit-Nachrichten | Ja (via Webhook) | Nein (nur Polling) |
| Historische Nachrichten | Nein | Ja (kann Verlauf abfragen) |
| Setup-Komplexität | Nur App-Manifest | Erfordert Admin-Consent + Token-Flow |
| Funktioniert offline | Nein (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.
- In Entra ID (Azure AD) App Registration, füge Microsoft Graph Application-Berechtigungen hinzu:
ChannelMessage.Read.All(Channel-Anhänge + Verlauf)Chat.Read.AlloderChatMessage.Read.All(Gruppenchats)
- Erteile Admin-Consent für den Tenant.
- Erhöhe die Teams-App Manifest-Version, lade sie neu hoch und installiere die App in Teams neu.
- 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(Standard3978)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) odernewline, 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>
- Direktnachrichten teilen die Main-Session (
Reply Style: Threads vs Posts
Teams hat kürzlich zwei Channel-UI-Stile über dasselbe zugrunde liegende Datenmodell eingeführt:
| Stil | Beschreibung | Empfohlener replyStyle |
|---|---|---|
| Posts (klassisch) | Nachrichten erscheinen als Karten mit Thread-Antworten darunter | thread (Standard) |
| Threads (Slack-ähnlich) | Nachrichten fließen linear, mehr wie Slack | top-level |
Das Problem: Die Teams-API zeigt nicht, welchen UI-Stil ein Channel nutzt. Wenn du den falschen replyStyle verwendest:
threadin einem Threads-Style-Channel → Antworten erscheinen unpassend verschachtelttop-levelin 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:
| Kontext | Wie Dateien gesendet werden | Setup benötigt |
|---|---|---|
| DMs | FileConsentCard → User akzeptiert → Bot lädt hoch | Funktioniert out of the box |
| Gruppenchats/Channels | Upload zu SharePoint → Sharing-Link teilen | Erfordert sharePointSiteId + Graph-Berechtigungen |
| Bilder (jeder Kontext) | Base64-kodiert inline | Funktioniert 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
-
Füge Graph API-Berechtigungen hinzu in Entra ID (Azure AD) → App Registration:
Sites.ReadWrite.All(Application) - Dateien zu SharePoint hochladenChat.Read.All(Application) - optional, ermöglicht Pro-User-Sharing-Links
-
Erteile Admin-Consent für den Tenant.
-
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" -
Konfiguriere OpenClaw:
{ channels: { msteams: { // ... andere Config ... sharePointSiteId: "contoso.sharepoint.com,guid1,guid2", }, }, }
Sharing-Verhalten
| Berechtigung | Sharing-Verhalten |
|---|---|
Nur Sites.ReadWrite.All | Organisationsweiter Sharing-Link (jeder in der Org kann zugreifen) |
Sites.ReadWrite.All + Chat.Read.All | Pro-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
| Szenario | Ergebnis |
|---|---|
Gruppenchat + Datei + sharePointSiteId konfiguriert | Upload zu SharePoint, Sharing-Link senden |
Gruppenchat + Datei + kein sharePointSiteId | Versuch OneDrive-Upload (kann fehlschlagen), nur Text senden |
| Persönlicher Chat + Datei | FileConsentCard-Flow (funktioniert ohne SharePoint) |
| Jeder Kontext + Bild | Base64-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.jsonaufgezeichnet. - 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-Typ | Format | Beispiel |
|---|---|---|
| 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/Channel | conversation:<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/configurationfürdmPolicyund 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:
| Feature | Standard-Channels | Private Channels |
|---|---|---|
| Bot-Installation | Ja | Eingeschränkt |
| Echtzeit-Nachrichten (Webhook) | Ja | Funktioniert möglicherweise nicht |
| RSC-Berechtigungen | Ja | Verhalten kann abweichen |
| @mentions | Ja | Wenn Bot zugänglich ist |
| Graph API-Verlauf | Ja | Ja (mit Berechtigungen) |
Workarounds, wenn private Channels nicht funktionieren:
- Nutze Standard-Channels für Bot-Interaktionen
- Nutze DMs - User können den Bot immer direkt anschreiben
- 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=falseoder 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ürcolor.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
- Verifiziere, dass
webApplicationInfo.idexakt mit deiner Bot-App-ID übereinstimmt - Lade die App neu hoch und installiere sie im Team/Chat neu
- Prüfe, ob dein Org-Admin RSC-Berechtigungen blockiert hat
- Bestätige, dass du den richtigen Scope nutzt:
ChannelMessage.Read.Groupfür Teams,ChatMessage.Read.Chatfür Gruppenchats
Referenzen
- Azure Bot erstellen - Azure Bot Setup-Guide
- Teams Developer Portal - Teams-Apps erstellen/verwalten
- Teams-App-Manifest-Schema
- Channel-Nachrichten mit RSC empfangen
- RSC-Berechtigungen-Referenz
- Teams Bot File Handling (Channel/Gruppe erfordert Graph)
- Proaktive Nachrichten