Microsoft Teams (Plugin)
„Lasst, die ihr eintretet, alle Hoffnung fahren.”
Aktualisiert: 2026-01-21
Status: Text + DM-Anhänge werden unterstützt; Kanal-/Gruppen-Dateiversand 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 in der Kerninstallation enthalten.
Breaking Change (2026.1.15): MS Teams wurde aus dem Kern verschoben. Wenn du es verwendest, musst du das Plugin installieren.
Begründung: hält Kerninstallationen schlanker und ermöglicht unabhängige Updates der MS Teams-Abhängigkeiten.
Installation über CLI (npm-Registry):
openclaw plugins install @openclaw/msteams
Lokaler Checkout (wenn aus einem Git-Repo ausgeführt):
openclaw plugins install ./extensions/msteams
Wenn du Teams während der Konfiguration/des Onboardings auswählst und ein Git-Checkout erkannt wird, bietet OpenClaw automatisch den lokalen Installationspfad an.
Details: Plugins
Schnelleinrichtung (Einsteiger)
- Installiere das Microsoft Teams-Plugin.
- Erstelle einen Azure Bot (App-ID + Client-Secret + Tenant-ID).
- Konfiguriere OpenClaw mit diesen Zugangsdaten.
- Exponiere
/api/messages(Standard Port 3978) über eine öffentliche URL oder einen Tunnel. - 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 verwende groupPolicy: "open", um jedes Mitglied zuzulassen, mit Mention-Gating).
Ziele
- Mit OpenClaw über Teams-DMs, Gruppenchats oder Kanäle kommunizieren.
- Routing deterministisch halten: Antworten gehen immer zum Kanal zurück, über den sie angekommen sind.
- Sicheres Kanalverhalten als Standard (Erwähnungen erforderlich, sofern nicht anders konfiguriert).
Konfigurationsschreibvorgänge
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 } },
}
Zugriffssteuerung (DMs + Gruppen)
DM-Zugriff
- Standard:
channels.msteams.dmPolicy = "pairing". Unbekannte Absender werden ignoriert, bis sie genehmigt werden. channels.msteams.allowFromsollte stabile AAD-Objekt-IDs verwenden.- UPNs/Anzeigenamen sind veränderlich; direktes Matching ist standardmäßig deaktiviert und nur mit
channels.msteams.dangerouslyAllowNameMatching: trueaktiviert. - Der Assistent kann bei entsprechenden Berechtigungen Namen über Microsoft Graph zu IDs auflösen.
Gruppenzugriff
- Standard:
channels.msteams.groupPolicy = "allowlist"(blockiert, es sei denn, du fügstgroupAllowFromhinzu). Verwendechannels.defaults.groupPolicy, um den Standard zu überschreiben, wenn nicht gesetzt. channels.msteams.groupAllowFromsteuert, welche Absender in Gruppenchats/Kanälen auslösen können (Fallback aufchannels.msteams.allowFrom).- Setze
groupPolicy: "open", um jedes Mitglied zuzulassen (standardmäßig weiterhin mit Mention-Gating). - Um keine Kanäle zu erlauben, setze
channels.msteams.groupPolicy: "disabled".
Beispiel:
{
channels: {
msteams: {
groupPolicy: "allowlist",
groupAllowFrom: ["[email protected]"],
},
},
}
Teams + Kanal-Allowlist
- Begrenze Gruppen-/Kanalantworten, indem du Teams und Kanäle unter
channels.msteams.teamsauflistest. - Schlüssel sollten stabile Team-IDs und Kanal-Konversations-IDs verwenden.
- Wenn
groupPolicy="allowlist"und eine Teams-Allowlist vorhanden ist, werden nur gelistete Teams/Kanäle akzeptiert (mit Mention-Gating). - Der Konfigurationsassistent akzeptiert
Team/Channel-Einträge und speichert sie für dich. - Beim Start löst OpenClaw Team-/Kanal- und Benutzer-Allowlist-Namen zu IDs auf (wenn Graph-Berechtigungen dies erlauben)
und protokolliert die Zuordnung; nicht aufgelöste Team-/Kanalnamen werden wie eingegeben beibehalten, aber standardmäßig beim Routing ignoriert, es sei denn,
channels.msteams.dangerouslyAllowNameMatching: trueist aktiviert.
Beispiel:
{
channels: {
msteams: {
groupPolicy: "allowlist",
teams: {
"My Team": {
channels: {
General: { requireMention: true },
},
},
},
},
},
}
Funktionsweise
- 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 unten aufgeführten RSC-Berechtigungen enthält.
- Lade die Teams-App in ein Team hoch oder 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-Einrichtung (Voraussetzungen)
Bevor du OpenClaw konfigurierst, musst du eine Azure Bot-Ressource erstellen.
Schritt 1: Azure Bot erstellen
-
Gehe zu Create Azure Bot
-
Fülle den Tab Basics 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 Entwicklung/Tests Type of App Single Tenant (empfohlen – siehe Hinweis unten) Creation type Create new Microsoft App ID
Hinweis zur Einstellung: Die Erstellung neuer Multi-Tenant-Bots wurde nach dem 31.07.2025 eingestellt. Verwende Single Tenant für neue Bots.
- Klicke auf Review + create → Create (ca. 1-2 Minuten warten)
Schritt 2: Zugangsdaten abrufen
- Gehe zu deiner Azure Bot-Ressource → Configuration
- Kopiere die Microsoft App ID → dies ist deine
appId - Klicke auf Manage Password → gehe zur App-Registrierung
- Unter Certificates & secrets → New client secret → kopiere den Value → dies ist dein
appPassword - Gehe zu Overview → kopiere die Directory (tenant) ID → dies ist deine
tenantId
Schritt 3: Messaging-Endpunkt konfigurieren
- In Azure Bot → Configuration
- Setze den Messaging endpoint auf deine Webhook-URL:
- Produktion:
https://your-domain.com/api/messages - Lokale Entwicklung: Verwende einen Tunnel (siehe Lokale Entwicklung unten)
- Produktion:
Schritt 4: Teams-Kanal aktivieren
- In Azure Bot → Channels
- Klicke auf Microsoft Teams → Configure → Save
- Akzeptiere die Nutzungsbedingungen
Lokale Entwicklung (Tunneling)
Teams kann localhost nicht erreichen. Verwende einen Tunnel für die lokale Entwicklung:
Option A: ngrok
ngrok http 3978
# Kopiere die https-URL, z. B. https://abc123.ngrok.io
# Setze den Messaging-Endpunkt auf: https://abc123.ngrok.io/api/messages
Option B: Tailscale Funnel
tailscale funnel 3978
# Verwende deine Tailscale-Funnel-URL als Messaging-Endpunkt
Teams Developer Portal (Alternative)
Anstatt manuell eine Manifest-ZIP-Datei zu erstellen, kannst du das Teams Developer Portal verwenden:
- 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 die Bereiche: Personal, Team, Group Chat
- Klicke auf Distribute → Download app package
- In Teams: Apps → Manage your apps → Upload a custom app → wähle die ZIP-Datei
Dies ist oft einfacher als das manuelle Bearbeiten von JSON-Manifesten.
Bot testen
Option A: Azure Web Chat (zuerst Webhook verifizieren)
- Im Azure Portal → deine Azure Bot-Ressource → Test in Web Chat
- Sende eine Nachricht – du solltest eine Antwort sehen
- Dies bestätigt, dass dein Webhook-Endpunkt funktioniert, bevor du Teams einrichtest
Option B: Teams (nach App-Installation)
- Installiere die Teams-App (Sideload oder Organisationskatalog)
- Finde den Bot in Teams und sende eine DM
- Prüfe die Gateway-Logs auf eingehende Aktivität
Einrichtung (minimaler Textmodus)
-
Microsoft Teams-Plugin installieren
- Von npm:
openclaw plugins install @openclaw/msteams - Aus 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
- Einen
bot-Eintrag mitbotId = <App ID>einfügen. - Bereiche:
personal,team,groupChat. supportsFiles: true(erforderlich für Dateibehandlung im persönlichen Bereich).- RSC-Berechtigungen hinzufügen (unten).
- Icons erstellen:
outline.png(32x32) undcolor.png(192x192). - Alle drei Dateien zusammenzippen:
manifest.json,outline.png,color.png.
- 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 Konfigurationsschlüsseln verwenden:
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
-
Bot-Endpunkt
- Setze den Azure Bot Messaging-Endpunkt auf:
https://<host>:3978/api/messages(oder deinen gewählten Pfad/Port).
- Setze den Azure Bot Messaging-Endpunkt auf:
-
Gateway starten
- Der Teams-Kanal startet automatisch, wenn das Plugin installiert ist und eine
msteams-Konfiguration mit Zugangsdaten existiert.
- Der Teams-Kanal startet automatisch, wenn das Plugin installiert ist und eine
Historienkontext
channels.msteams.historyLimitsteuert, wie viele kürzliche Kanal-/Gruppennachrichten in den Prompt eingebunden werden.- Fallback auf
messages.groupChat.historyLimit. Setze0zum Deaktivieren (Standard 50). - DM-Historie kann mit
channels.msteams.dmHistoryLimit(Benutzer-Turns) begrenzt werden. Pro-Benutzer-Überschreibungen:channels.msteams.dms["<user_id>"].historyLimit.
Aktuelle Teams RSC-Berechtigungen (Manifest)
Dies sind die bestehenden resourceSpecific-Berechtigungen in unserem Teams-App-Manifest. Sie gelten nur innerhalb des Teams/Chats, in dem die App installiert ist.
Für Kanäle (Team-Bereich):
ChannelMessage.Read.Group(Application) – alle Kanalnachrichten 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 (anonymisiert)
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-Hinweise (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 verwenden möchtest (personal,team,groupChat).bots[].supportsFiles: trueist für die Dateibehandlung im persönlichen Bereich erforderlich.authorization.permissions.resourceSpecificmuss Kanal-Lese-/Sendeberechtigungen enthalten, wenn du Kanalverkehr möchtest.
Bestehende 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) - Erneut zippen – das Manifest mit Icons (
manifest.json,outline.png,color.png) - Die neue ZIP-Datei hochladen:
- 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-Kanäle: Installiere die App in jedem Team neu, damit neue Berechtigungen wirksam werden
- Teams vollständig beenden und neu starten (nicht nur das Fenster schließen), um zwischengespeicherte App-Metadaten zu löschen
Fähigkeiten: Nur RSC vs. Graph
Mit nur Teams RSC (App installiert, keine Graph-API-Berechtigungen)
Funktioniert:
- Text-Inhalt von Kanalnachrichten lesen.
- Text-Inhalt von Kanalnachrichten senden.
- Persönliche (DM)-Dateianhänge empfangen.
Funktioniert NICHT:
- Kanal-/Gruppen-Bild- oder Dateiinhalte (Payload enthält nur HTML-Stub).
- Anhänge aus SharePoint/OneDrive herunterladen.
- Nachrichtenhistorie lesen (über das Live-Webhook-Event hinaus).
Mit Teams RSC + Microsoft Graph Application-Berechtigungen
Zusätzlich:
- Gehostete Inhalte herunterladen (in Nachrichten eingefügte Bilder).
- Dateianhänge aus SharePoint/OneDrive herunterladen.
- Kanal-/Chat-Nachrichtenhistorie über Graph lesen.
RSC vs. Graph API
| Fähigkeit | RSC-Berechtigungen | Graph API |
|---|---|---|
| Echtzeitnachrichten | Ja (über Webhook) | Nein (nur Polling) |
| Historische Nachr. | Nein | Ja (Historie abfragen) |
| Setup-Komplexität | Nur App-Manifest | Admin-Consent + Token-Flow erforderlich |
| Funktioniert offline | Nein (muss laufen) | Ja (jederzeit abfragen) |
Fazit: RSC ist für Echtzeit-Listening; Graph API ist für historischen Zugriff. Um versäumte Nachrichten während Offline-Zeiten nachzuholen, benötigst du die Graph API mit ChannelMessage.Read.All (erfordert Admin-Consent).
Graph-fähige Medien + Historie (erforderlich für Kanäle)
Wenn du Bilder/Dateien in Kanälen benötigst oder Nachrichtenhistorie 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(Kanalanhänge + Historie)Chat.Read.AlloderChatMessage.Read.All(Gruppenchats)
- Admin-Consent für den Mandanten erteilen.
- Die Teams-App Manifest-Version erhöhen, erneut hochladen und die App in Teams neu installieren.
- Teams vollständig beenden und neu starten, um zwischengespeicherte App-Metadaten zu löschen.
Zusätzliche Berechtigung für Benutzer-Erwähnungen: Benutzer-@Mentions funktionieren standardmäßig für Benutzer in der Konversation. Wenn du jedoch Benutzer dynamisch suchen und erwähnen möchtest, die nicht in der aktuellen Konversation sind, füge die User.Read.All (Application)-Berechtigung hinzu und erteile Admin-Consent.
Bekannte Einschränkungen
Webhook-Timeouts
Teams liefert Nachrichten über HTTP-Webhooks. Wenn die Verarbeitung zu lange dauert (z. B. langsame LLM-Antworten), können folgende Probleme auftreten:
- Gateway-Timeouts
- Teams wiederholt die Nachricht (verursacht Duplikate)
- Verworfene Antworten
OpenClaw behandelt dies, indem es schnell zurückkehrt und Antworten proaktiv sendet, aber sehr langsame Antworten können trotzdem 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 dargestellt
- Adaptive Cards werden für Umfragen und beliebige Card-Sends unterstützt (siehe unten)
Konfiguration
Wichtige Einstellungen (siehe /gateway/configuration für gemeinsame Kanalmuster):
channels.msteams.enabled: Kanal 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: DM-Allowlist (AAD-Objekt-IDs empfohlen). Der Assistent löst Namen während des Setups zu IDs auf, wenn Graph-Zugriff verfügbar ist.channels.msteams.dangerouslyAllowNameMatching: Notfall-Schalter, um veränderliches UPN-/Anzeigenamen-Matching und direktes Team-/Kanalnamen-Routing wieder zu aktivieren.channels.msteams.textChunkLimit: Ausgehende Text-Chunk-Größe.channels.msteams.chunkMode:length(Standard) odernewline, um an Leerzeilen (Absatzgrenzen) vor dem Längen-Chunking aufzuteilen.channels.msteams.mediaAllowHosts: Allowlist für eingehende Anhang-Hosts (Standard: Microsoft/Teams-Domains).channels.msteams.mediaAuthAllowHosts: Allowlist für das Anhängen von Authorization-Headern bei Medien-Retries (Standard: Graph + Bot Framework-Hosts).channels.msteams.requireMention: @Mention in Kanälen/Gruppen erfordern (Standard true).channels.msteams.replyStyle:thread | top-level(siehe Antwortstil).channels.msteams.teams.<teamId>.replyStyle: Pro-Team-Überschreibung.channels.msteams.teams.<teamId>.requireMention: Pro-Team-Überschreibung.channels.msteams.teams.<teamId>.tools: Standard-Pro-Team-Tool-Richtlinienüberschreibungen (allow/deny/alsoAllow), die verwendet werden, wenn eine Kanalüberschreibung fehlt.channels.msteams.teams.<teamId>.toolsBySender: Standard-Pro-Team-Pro-Absender-Tool-Richtlinienüberschreibungen ("*"Wildcard unterstützt).channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: Pro-Kanal-Überschreibung.channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: Pro-Kanal-Überschreibung.channels.msteams.teams.<teamId>.channels.<conversationId>.tools: Pro-Kanal-Tool-Richtlinienüberschreibungen (allow/deny/alsoAllow).channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: Pro-Kanal-Pro-Absender-Tool-Richtlinienüberschreibungen ("*"Wildcard unterstützt).toolsBySender-Schlüssel sollten explizite Präfixe verwenden:id:,e164:,username:,name:(Legacy-Schlüssel ohne Präfix werden weiterhin nur aufid:abgebildet).channels.msteams.sharePointSiteId: SharePoint-Site-ID für Datei-Uploads in Gruppenchats/Kanälen (siehe Dateien in Gruppenchats senden).
Routing & Sessions
- Session-Schlüssel folgen dem Standard-Agent-Format (siehe /concepts/session):
- Direktnachrichten teilen die Hauptsession (
agent:<agentId>:<mainKey>). - Kanal-/Gruppennachrichten verwenden die Konversations-ID:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- Direktnachrichten teilen die Hauptsession (
Antwortstil: Threads vs. Posts
Teams hat kürzlich zwei Kanal-UI-Stile über dasselbe zugrunde liegende Datenmodell eingeführt:
| Stil | Beschreibung | Empfohlener replyStyle |
|---|---|---|
| Posts (klassisch) | Nachrichten erscheinen als Karten mit Threaded-Antworten darunter | thread (Standard) |
| Threads (Slack-ähnlich) | Nachrichten fließen linear, ähnlich wie Slack | top-level |
Das Problem: Die Teams-API gibt nicht preis, welchen UI-Stil ein Kanal verwendet. Wenn du den falschen replyStyle verwendest:
threadin einem Threads-Stil-Kanal → Antworten erscheinen unpassend verschachtelttop-levelin einem Posts-Stil-Kanal → Antworten erscheinen als separate Top-Level-Posts statt im Thread
Lösung: Konfiguriere 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 Teams Bot File APIs.
- Kanäle/Gruppen: Anhänge befinden sich im M365-Speicher (SharePoint/OneDrive). Der Webhook-Payload enthält nur einen HTML-Stub, nicht die tatsächlichen Datei-Bytes. Graph-API-Berechtigungen sind erforderlich, um Kanalanhänge herunterzuladen.
Ohne Graph-Berechtigungen werden Kanalnachrichten mit Bildern als reiner Text empfangen (der Bildinhalt ist für den Bot nicht zugänglich).
Standardmäßig lädt OpenClaw nur Medien von Microsoft/Teams-Hostnamen herunter. Überschreibe mit channels.msteams.mediaAllowHosts (verwende ["*"], um jeden Host zu erlauben).
Authorization-Header werden nur für Hosts in channels.msteams.mediaAuthAllowHosts angehängt (Standard: Graph + Bot Framework-Hosts). Halte diese Liste strikt (vermeide Multi-Tenant-Suffixe).
Dateien in Gruppenchats senden
Bots können Dateien in DMs über den FileConsentCard-Ablauf senden (integriert). Allerdings erfordert das Senden von Dateien in Gruppenchats/Kanälen zusätzliche Einrichtung:
| Kontext | Wie Dateien gesendet werden | Benötigtes Setup |
|---|---|---|
| DMs | FileConsentCard → Benutzer akzeptiert → Bot lädt hoch | Funktioniert sofort |
| Gruppenchats/Kanäle | Upload zu SharePoint → Freigabelink teilen | Erfordert sharePointSiteId + Graph-Berechtigungen |
| Bilder (jeder Kontext) | Base64-kodiert inline | Funktioniert sofort |
Warum Gruppenchats SharePoint benötigen
Bots haben kein persönliches OneDrive-Laufwerk (der /me/drive Graph-API-Endpunkt funktioniert nicht für Application-Identitäten). Um Dateien in Gruppenchats/Kanälen zu senden, lädt der Bot auf eine SharePoint-Site hoch und erstellt einen Freigabelink.
Einrichtung
-
Graph-API-Berechtigungen hinzufügen in Entra ID (Azure AD) → App Registration:
Sites.ReadWrite.All(Application) – Dateien zu SharePoint hochladenChat.Read.All(Application) – optional, ermöglicht Pro-Benutzer-Freigabelinks
-
Admin-Consent für den Mandanten erteilen.
-
SharePoint-Site-ID abrufen:
# 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 unter "contoso.sharepoint.com/sites/BotFiles" curl -H "Authorization: Bearer $TOKEN" \ "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles" # Antwort enthält: "id": "contoso.sharepoint.com,guid1,guid2" -
OpenClaw konfigurieren:
{ channels: { msteams: { // ... andere Konfiguration ... sharePointSiteId: "contoso.sharepoint.com,guid1,guid2", }, }, }
Freigabeverhalten
| Berechtigung | Freigabeverhalten |
|---|---|
Nur Sites.ReadWrite.All | Organisationsweiter Freigabelink (jeder in der Org kann zugreifen) |
Sites.ReadWrite.All + Chat.Read.All | Pro-Benutzer-Freigabelink (nur Chat-Mitglieder können zugreifen) |
Pro-Benutzer-Freigabe 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 organisationsweite Freigabe zurück.
Fallback-Verhalten
| Szenario | Ergebnis |
|---|---|
Gruppenchat + Datei + sharePointSiteId konfiguriert | Upload zu SharePoint, Freigabelink senden |
Gruppenchat + Datei + kein sharePointSiteId | OneDrive-Upload-Versuch (kann fehlschlagen), nur Text senden |
| Persönlicher Chat + Datei | FileConsentCard-Ablauf (funktioniert ohne SharePoint) |
| Jeder Kontext + Bild | Base64-kodiert inline (funktioniert ohne SharePoint) |
Dateispeicherort
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.jsonaufgezeichnet. - Das Gateway muss online bleiben, um Stimmen aufzuzeichnen.
- Umfragen veröffentlichen noch keine automatischen Ergebniszusammenfassungen (bei Bedarf die Store-Datei inspizieren).
Adaptive Cards (beliebig)
Sende beliebiges Adaptive Card-JSON an Teams-Benutzer oder -Konversationen über das 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 documentation für Card-Schema und Beispiele. Für Details zum Zielformat siehe Zielformate unten.
Zielformate
MSTeams-Ziele verwenden Präfixe, um zwischen Benutzern und Konversationen zu unterscheiden:
| Zieltyp | Format | Beispiel |
|---|---|---|
| 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/Kanal | conversation:<conversation-id> | conversation:19:[email protected] |
| Gruppe/Kanal (roh) | <conversation-id> | 19:[email protected] (wenn @thread enthalten) |
CLI-Beispiele:
# An einen Benutzer nach ID senden
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"
# An einen Benutzer nach Anzeigename senden (löst Graph-API-Suche aus)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"
# An einen Gruppenchat oder Kanal senden
openclaw message send --channel msteams --target "conversation:19:[email protected]" --message "Hello"
# Eine Adaptive Card an eine Konversation 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 Gruppe/Team aufgelöst. Verwende immer user:, wenn du Personen nach Anzeigename adressierst.
Proaktive Nachrichten
- Proaktive Nachrichten sind nur nachdem ein Benutzer interagiert hat möglich, da wir zu diesem Zeitpunkt Konversationsreferenzen speichern.
- Siehe
/gateway/configurationfürdmPolicyund Allowlist-Gating.
Team- und Kanal-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-dekodieren)
Kanal-URL:
https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
└─────────────────────────┘
Kanal-ID (URL-dekodieren)
Für die Konfiguration:
- Team-ID = Pfadsegment nach
/team/(URL-dekodiert, z. B.19:[email protected]) - Kanal-ID = Pfadsegment nach
/channel/(URL-dekodiert) groupId-Query-Parameter ignorieren
Private Kanäle
Bots haben eingeschränkte Unterstützung in privaten Kanälen:
| Feature | Standard-Kanäle | Private Kanäle |
|---|---|---|
| Bot-Installation | Ja | Eingeschränkt |
| Echtzeitnachrichten (Webhook) | Ja | Funktioniert evtl. nicht |
| RSC-Berechtigungen | Ja | Kann anders reagieren |
| @Mentions | Ja | Wenn Bot erreichbar |
| Graph API-Historie | Ja | Ja (mit Berechtigungen) |
Workarounds, wenn private Kanäle nicht funktionieren:
- Standard-Kanäle für Bot-Interaktionen verwenden
- DMs verwenden – Benutzer können den Bot immer direkt anschreiben
- Graph API für historischen Zugriff verwenden (erfordert
ChannelMessage.Read.All)
Fehlerbehebung
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; setze
channels.msteams.requireMention=falseoder konfiguriere 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 beim manuellen Testen ohne Azure JWT – bedeutet, der Endpunkt ist erreichbar, aber die Authentifizierung ist fehlgeschlagen. Verwende Azure Web Chat zum ordnungsgemäßen Testen.
Manifest-Upload-Fehler
- „Icon file cannot be empty”: Das Manifest referenziert Icon-Dateien mit 0 Bytes. 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. Zuerst finden und deinstallieren, oder 5-10 Minuten auf Propagierung warten.
- „Something went wrong” beim Upload: Lade stattdessen über https://admin.teams.microsoft.com hoch, öffne die Browser-DevTools (F12) → Netzwerk-Tab und prüfe den Response-Body auf den tatsächlichen Fehler.
- Sideload schlägt fehl: Versuche „Upload an app to your org’s app catalog” anstelle von „Upload a custom app” – dies umgeht oft Sideload-Einschränkungen.
RSC-Berechtigungen funktionieren nicht
- Überprüfe, ob
webApplicationInfo.idexakt mit der Bot-App-ID übereinstimmt - App erneut hochladen und im Team/Chat neu installieren
- Prüfe, ob dein Org-Admin RSC-Berechtigungen blockiert hat
- Bestätige, dass du den richtigen Bereich verwendest:
ChannelMessage.Read.Groupfür Teams,ChatMessage.Read.Chatfür Gruppenchats
Referenzen
- Create Azure Bot – Azure Bot-Einrichtungsanleitung
- Teams Developer Portal – Teams-Apps erstellen/verwalten
- Teams app manifest schema
- Receive channel messages with RSC
- RSC permissions reference
- Teams bot file handling (Kanal/Gruppe erfordert Graph)
- Proactive messaging