Microsoft Teams Plugin für OpenClaw einrichten
Plugin erforderlich
Abschnitt betitelt „Plugin erforderlich“Microsoft Teams wird als Plugin ausgeliefert und ist nicht in der Core-Installation enthalten.
Breaking Change (15.01.2026): Microsoft Teams wurde aus dem Core entfernt. Wenn du es nutzt, musst du das Plugin installieren. Das ist sinnvoll: So bleibt die Core-Installation schlank und die Microsoft Teams Abhängigkeiten können unabhängig aktualisiert werden.
Installation via CLI (npm Registry):
openclaw plugins install @openclaw/msteamsLokaler Checkout (wenn du aus einem Git-Repo arbeitest):
openclaw plugins install ./path/to/local/msteams-pluginWenn du Teams während des Setups auswählst und ein Git-Checkout erkannt wird, bietet OpenClaw den lokalen Installationspfad automatisch an.
Details: Plugins
Schnelles Setup (Anfänger)
Abschnitt betitelt „Schnelles Setup (Anfänger)“- Installiere das Microsoft Teams Plugin.
- Erstelle einen Azure Bot (App ID + Client Secret + Tenant ID).
- Konfiguriere OpenClaw mit diesen Credentials.
- Gib
/api/messages(Standard-Port 3978) über eine öffentliche URL oder einen Tunnel frei. - Installiere das Teams App-Paket und starte das Gateway.
Minimale Config:
{ channels: { msteams: { enabled: true, appId: "<APP_ID>", appPassword: "<APP_PASSWORD>", tenantId: "<TENANT_ID>", webhook: { port: 3978, path: "/api/messages" }, }, },}Hinweis: Gruppen-Chats sind standardmäßig blockiert (channels.msteams.groupPolicy: "allowlist"). Um Antworten in Gruppen zu erlauben, setze channels.msteams.groupAllowFrom (oder nutze groupPolicy: "open", um jedem Mitglied den Zugriff per Mention zu erlauben).
- Mit OpenClaw über Teams DMs, Gruppen-Chats oder Channels kommunizieren und dabei das Routing deterministisch halten (Antworten gehen immer an den Ursprungs-Channel zurück).
- Standardmäßig auf sicheres Channel-Verhalten setzen (Mentions sind Pflicht, außer du konfigurierst es anders).
Config-Schreibzugriff
Abschnitt betitelt „Config-Schreibzugriff“Standardmäßig darf Microsoft Teams Konfigurations-Updates schreiben, die über /config set|unset ausgelöst werden (erfordert commands.config: true).
Deaktivieren mit:
{ channels: { msteams: { configWrites: false } },}Zugriffskontrolle (DMs + Gruppen)
Abschnitt betitelt „Zugriffskontrolle (DMs + Gruppen)“DM-Zugriff
- Standardmäßig gilt:
channels.msteams.dmPolicy = "pairing". Unbekannte Absender werden ignoriert, bis du sie bestätigst. - Für
channels.msteams.allowFromsolltest du stabile AAD-Objekt-IDs verwenden. - UPNs und Anzeigenamen können sich ändern; das direkte Matching ist standardmäßig deaktiviert und wird nur mit
channels.msteams.dangerouslyAllowNameMatching: trueaktiviert. - Der Wizard kann Namen über Microsoft Graph in IDs auflösen, wenn die Zugangsdaten das zulassen.
Gruppen-Zugriff
- Standardmäßig gilt:
channels.msteams.groupPolicy = "allowlist"(alles ist blockiert, außer du fügstgroupAllowFromhinzu). Nutzechannels.defaults.groupPolicy, um den Standardwert zu überschreiben, falls nichts gesetzt ist. channels.msteams.groupAllowFromsteuert, welche Absender Trigger in Gruppen-Chats oder Kanälen auslösen dürfen (greift als Fallback aufchannels.msteams.allowFromzurück).- Setze
groupPolicy: "open", um allen Mitgliedern den Zugriff zu erlauben (standardmäßig ist trotzdem eine Erwähnung/Mention nötig). - Wenn du gar keine Kanäle erlauben willst, setze
channels.msteams.groupPolicy: "disabled".
Beispiel:
{ channels: { msteams: { groupPolicy: "allowlist", groupAllowFrom: ["user@org.com"], }, },}Teams + Kanal-Allowlist
- Grenze Antworten in Gruppen oder Kanälen ein, indem du Teams und Kanäle unter
channels.msteams.teamsauflistest. - Die Keys sollten stabile Team-IDs und Kanal-Konversations-IDs sein.
- Wenn
groupPolicy="allowlist"aktiv ist und eine Teams-Allowlist existiert, werden nur die aufgelisteten Teams/Kanäle akzeptiert (Mention-Pflicht). - Der Konfigurations-Wizard akzeptiert
Team/Kanal-Einträge und speichert sie für dich. - Beim Start löst OpenClaw die Namen in der Team-, Kanal- und User-Allowlist in IDs auf (sofern Graph-Berechtigungen vorhanden sind) und loggt das Mapping. Nicht aufgelöste Team- oder Kanalnamen bleiben wie getippt erhalten, werden aber beim Routing ignoriert, außer
channels.msteams.dangerouslyAllowNameMatching: trueist aktiviert.
Beispiel:
{ channels: { msteams: { groupPolicy: "allowlist", teams: { "My Team": { channels: { General: { requireMention: true }, }, }, }, }, },}So funktioniert es
Abschnitt betitelt „So funktioniert es“- Installiere das Microsoft Teams Plugin.
- Erstelle einen Azure Bot (App ID + Secret + Tenant ID).
- Erstelle ein Teams App Package, das auf den Bot verweist und die unten genannten RSC-Berechtigungen enthält.
- Lade die Teams App in ein Team hoch (oder installiere sie im persönlichen Bereich für DMs).
- Konfiguriere
msteamsin der~/.openclaw/openclaw.json(oder über Umgebungsvariablen) und starte das Gateway. - Das Gateway lauscht standardmäßig auf Bot Framework Webhook-Traffic unter
/api/messages.
Azure Bot Setup (Voraussetzungen)
Abschnitt betitelt „Azure Bot Setup (Voraussetzungen)“Bevor du OpenClaw konfigurierst, musst du eine Azure Bot Ressource erstellen.
Schritt 1: Azure Bot erstellen
Abschnitt betitelt „Schritt 1: Azure Bot erstellen“-
Gehe zu Azure Bot erstellen
-
Fülle den Reiter Grundlagen aus:
Feld Wert Bot handle Dein Bot-Name, z. B. openclaw-msteams(muss eindeutig sein)Subscription Wähle dein Azure-Abonnement aus Resource group Neu erstellen oder vorhandene nutzen Pricing tier Free für Entwicklung/Tests Type of App Single Tenant (empfohlen - siehe Hinweis unten) Creation type Create new Microsoft App ID
Veraltungshinweis: 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
Abschnitt betitelt „Schritt 2: Zugangsdaten abrufen“- Gehe zu deiner Azure Bot Ressource → Configuration
- Kopiere die Microsoft App ID → das ist deine
appId - Klicke auf Manage Password → du wirst zur App-Registrierung weitergeleitet
- Unter Certificates & secrets → New client secret → kopiere den Value → das ist dein
appPassword - Gehe zu Overview → kopiere die Directory (tenant) ID → das ist deine
tenantId
Schritt 3: Messaging-Endpunkt konfigurieren
Abschnitt betitelt „Schritt 3: Messaging-Endpunkt konfigurieren“- Im Azure Bot → Configuration
- Setze den Messaging endpoint auf deine Webhook-URL:
- Produktion:
https://deine-domain.com/api/messages - Lokale Entwicklung: Nutze einen Tunnel (siehe Lokale Entwicklung unten)
- Produktion:
Schritt 4: Teams-Kanal aktivieren
Abschnitt betitelt „Schritt 4: Teams-Kanal aktivieren“- Im Azure Bot → Channels
- Klicke auf Microsoft Teams → Configure → Save
- Akzeptiere die Nutzungsbedingungen
Lokale Entwicklung (Tunneling)
Abschnitt betitelt „Lokale Entwicklung (Tunneling)“Teams kann localhost nicht erreichen. Nutze 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/messagesOption B: Tailscale Funnel
tailscale funnel 3978# Use your Tailscale funnel URL as the messaging endpointTeams Developer Portal (Alternative)
Abschnitt betitelt „Teams Developer Portal (Alternative)“Anstatt das Manifest-ZIP manuell zu erstellen, kannst du das Teams Developer Portal nutzen. Das ist oft einfacher, als JSON-Dateien von Hand zu editieren.
- Klicke auf + New app
- Gib die Basis-Infos ein (Name, Beschreibung, Entwickler-Infos)
- Gehe zu App features → Bot
- Wähle Enter a bot ID manually und füge deine Azure Bot App ID ein
- Prüfe die 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 aus
Den Bot testen
Abschnitt betitelt „Den Bot testen“Option A: Azure Web Chat (zuerst den Webhook prüfen)
- Im Azure Portal → deine Azure Bot Ressource → Test in Web Chat
- Sende eine Nachricht – du solltest eine Antwort erhalten
- Das bestätigt, dass dein Webhook-Endpunkt funktioniert, bevor du mit dem Teams-Setup weitermachst
Option B: Teams (nach der App-Installation)
- Installiere die Teams-App (Sideloading oder Organisationskatalog)
- Suche den Bot in Teams und sende eine DM
- Prüfe die Gateway-Logs auf eingehende Aktivitäten
Setup (nur Text)
Abschnitt betitelt „Setup (nur Text)“-
Installiere das Microsoft Teams Plugin
- Über npm:
openclaw plugins install @openclaw/msteams - Aus einem lokalen Verzeichnis:
openclaw plugins install ./path/to/local/msteams-plugin
- Über npm:
-
Bot-Registrierung
- Erstelle einen Azure Bot (siehe oben) und notiere dir:
- App ID
- Client secret (App-Passwort)
- Tenant ID (single-tenant)
- Erstelle einen Azure Bot (siehe oben) und notiere dir:
-
Teams App Manifest
- Füge einen
bot-Eintrag mitbotId = <App ID>hinzu. - Scopes:
personal,team,groupChat. supportsFiles: true(erforderlich für das Dateihandling im Personal Scope).- Füge RSC-Berechtigungen hinzu (siehe unten).
- Erstelle Icons:
outline.png(32x32) undcolor.png(192x192). - Packe alle drei Dateien in ein ZIP:
manifest.json,outline.png,color.png.
- Füge einen
-
OpenClaw konfigurieren
{channels: {msteams: {enabled: true,appId: "<APP_ID>",appPassword: "<APP_PASSWORD>",tenantId: "<TENANT_ID>",webhook: { port: 3978, path: "/api/messages" },},},}Du kannst auch Umgebungsvariablen statt der Config-Keys nutzen:
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
-
Bot-Endpunkt
- 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 die
msteams-Konfiguration mit den entsprechenden Zugangsdaten existiert.
- Der Teams-Channel startet automatisch, wenn das Plugin installiert ist und die
Member-Info Action
Abschnitt betitelt „Member-Info Action“OpenClaw bietet eine Graph-basierte member-info Action für Microsoft Teams an. Damit können Agents und Automatisierungen Details zu Channel-Mitgliedern (Anzeigename, E-Mail, Rolle) direkt über Microsoft Graph abrufen.
Voraussetzungen:
Member.Read.GroupRSC-Berechtigung (bereits im empfohlenen Manifest enthalten)- Für teamübergreifende Abfragen:
User.Read.AllGraph Application Berechtigung mit Admin-Zustimmung
Die Action wird über channels.msteams.actions.memberInfo gesteuert (standardmäßig aktiviert, wenn Graph-Zugangsdaten vorhanden sind).
Verlaufskontext
Abschnitt betitelt „Verlaufskontext“channels.msteams.historyLimitsteuert, wie viele aktuelle Nachrichten aus Kanälen oder Gruppen in den Prompt einfließen.- Falls nichts konfiguriert ist, greift
messages.groupChat.historyLimit. Mit dem Wert0deaktivierst du die Funktion (Standardwert ist 50). - Der abgerufene Thread-Verlauf wird durch Sender-Allowlists (
allowFrom/groupAllowFrom) gefiltert. So stellt das Seeding des Thread-Kontexts sicher, dass nur Nachrichten von erlaubten Absendern enthalten sind. - Das Limit für DM-Verläufe kannst du mit
channels.msteams.dmHistoryLimitfestlegen (User-Turns). Mitchannels.msteams.dms["<user_id>"].historyLimitsind auch Overrides pro Nutzer möglich.
Aktuelle Teams RSC-Berechtigungen (Manifest)
Abschnitt betitelt „Aktuelle Teams RSC-Berechtigungen (Manifest)“Das sind die bestehenden resourceSpecific Berechtigungen in unserem Teams App-Manifest. Sie gelten ausschließlich innerhalb des Teams oder Chats, in dem die App installiert ist.
Für Kanäle (Team-Scope):
ChannelMessage.Read.Group(Application) – alle Kanalnachrichten empfangen, auch ohne @mentionChannelMessage.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 Gruppen-Chats:
ChatMessage.Read.Chat(Application) – alle Nachrichten in Gruppen-Chats empfangen, auch ohne @mention
Beispiel für ein Teams-Manifest (gekürzt)
Abschnitt betitelt „Beispiel für ein Teams-Manifest (gekürzt)“Minimales, gültiges Beispiel mit den erforderlichen Feldern. Ersetze die IDs und URLs durch deine eigenen Werte.
{ $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" }, ], }, },}Wichtige Hinweise zum Manifest
Abschnitt betitelt „Wichtige Hinweise zum Manifest“bots[].botIdmuss exakt mit der Azure Bot App ID übereinstimmen.webApplicationInfo.idmuss ebenfalls der Azure Bot App ID entsprechen.bots[].scopesmuss die Bereiche abdecken, die du nutzen möchtest (personal,team,groupChat).bots[].supportsFiles: trueist zwingend erforderlich, um Dateien im persönlichen Scope zu verarbeiten.authorization.permissions.resourceSpecificmuss Lese- und Schreibrechte für Kanäle enthalten, wenn du dort Traffic empfangen willst.
Eine bestehende App aktualisieren
Abschnitt betitelt „Eine bestehende App aktualisieren“Um eine bereits installierte Teams App zu aktualisieren (z. B. um RSC-Berechtigungen hinzuzufügen):
- Aktualisiere deine
manifest.jsonmit den neuen Einstellungen. - Erhöhe das
versionFeld (z. B. von1.0.0auf1.1.0). - Erstelle ein neues ZIP-Archiv mit dem Manifest und den Icons (
manifest.json,outline.png,color.png). - Lade das neue ZIP hoch:
- Option A (Teams Admin Center): Teams Admin Center → Teams-Apps → Apps verwalten → suche deine App → Neue Version hochladen.
- Option B (Sideload): In Teams → Apps → Deine Apps verwalten → Eine benutzerdefinierte App hochladen.
- Für Team-Kanäle: Installiere die App in jedem Team neu, damit die neuen Berechtigungen aktiv werden.
- Beende Teams komplett und starte es neu (nicht nur das Fenster schließen), um den Cache für App-Metadaten zu leeren.
Funktionen: Nur RSC vs. Graph
Abschnitt betitelt „Funktionen: Nur RSC vs. Graph“Mit nur Teams RSC (App installiert, keine Graph API Berechtigungen)
Abschnitt betitelt „Mit nur Teams RSC (App installiert, keine Graph API Berechtigungen)“Was funktioniert:
- Textinhalte von Kanalnachrichten lesen.
- Textinhalte in Kanälen senden.
- Dateianhänge in persönlichen Chats (DM) empfangen.
Was NICHT funktioniert:
- Bild- oder Dateiinhalte in Kanälen/Gruppen (Payload enthält nur einen HTML-Stub).
- Download von Anhängen, die in SharePoint oder OneDrive gespeichert sind.
- Nachrichtenverlauf lesen (über das Live-Webhook-Event hinaus).
Mit Teams RSC + Microsoft Graph Application Berechtigungen
Abschnitt betitelt „Mit Teams RSC + Microsoft Graph Application Berechtigungen“Zusätzliche Möglichkeiten:
- Download von gehosteten Inhalten (Bilder, die in Nachrichten kopiert wurden).
- Download von Dateianhängen aus SharePoint oder OneDrive.
- Nachrichtenverlauf von Kanälen/Chats über Graph auslesen.
RSC vs. Graph API
Abschnitt betitelt „RSC vs. Graph API“| Funktion | RSC-Berechtigungen | Graph API |
|---|---|---|
| Echtzeit-Nachrichten | Ja (via Webhook) | Nein (nur Polling) |
| Verlauf (Historie) | Nein | Ja (Abfrage möglich) |
| Setup-Aufwand | Nur App-Manifest | Erfordert Admin-Zustimmung + Token |
| Offline-Betrieb | Nein (muss laufen) | Ja (jederzeit abfragbar) |
Fazit: RSC ist für das Zuhören in Echtzeit gedacht; die Graph API nutzt du für den Zugriff auf den Verlauf. Um verpasste Nachrichten nachzuholen, während die App offline war, benötigst du die Graph API mit ChannelMessage.Read.All (erfordert Admin-Zustimmung).
Graph-aktivierte Medien + Verlauf (erforderlich für Channels)
Abschnitt betitelt „Graph-aktivierte Medien + Verlauf (erforderlich für Channels)“Wenn du Bilder oder Dateien in Channels nutzen oder den Nachrichtenverlauf abrufen möchtest, musst du Microsoft Graph-Berechtigungen aktivieren und die Admin-Zustimmung erteilen.
- In der Entra ID (Azure AD) App-Registrierung fügst du Microsoft Graph Application permissions hinzu:
ChannelMessage.Read.All(Channel-Anhänge + Verlauf)Chat.Read.AlloderChatMessage.Read.All(Gruppen-Chats)
- Erteile die Admin-Zustimmung für den Tenant.
- Erhöhe die Manifest-Version der Teams-App, lade sie neu hoch und installiere die App in Teams neu.
- Beende Teams vollständig und starte es neu, um den Cache der App-Metadaten zu leeren.
Zusätzliche Berechtigung für User-Mentions: @Mentions funktionieren standardmäßig für User in der Konversation. Wenn du jedoch User dynamisch suchen und erwähnen willst, die nicht in der aktuellen Konversation sind, füge die Berechtigung User.Read.All (Application) hinzu und erteile die Admin-Zustimmung.
Bekannte Einschränkungen
Abschnitt betitelt „Bekannte Einschränkungen“Webhook-Timeouts
Abschnitt betitelt „Webhook-Timeouts“Teams stellt Nachrichten über HTTP-Webhooks zu. Wenn die Verarbeitung zu lange dauert (z. B. bei langsamen LLM-Antworten), kann Folgendes passieren:
- Gateway-Timeouts
- Teams versucht die Nachricht erneut zu senden (was zu Duplikaten führt)
- Abgebrochene Antworten
OpenClaw löst das, indem es schnell antwortet und Replies proaktiv sendet. Sehr langsame Antworten können aber trotzdem zu Problemen führen.
Formatierung
Abschnitt betitelt „Formatierung“Teams-Markdown ist eingeschränkter als bei Slack oder Discord:
- Grundlegende Formatierung funktioniert: fett, kursiv,
code, Links - Komplexes Markdown (Tabellen, verschachtelte Listen) wird eventuell nicht korrekt gerendert
- Adaptive Cards werden für Umfragen und das Senden beliebiger Karten unterstützt (siehe unten)
Konfiguration
Abschnitt betitelt „Konfiguration“Wichtige Einstellungen (siehe /gateway/configuration für Shared Channel Patterns):
channels.msteams.enabled: Aktiviert oder deaktiviert den Channel.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 Object-IDs empfohlen). Der Wizard löst Namen während des Setups in IDs auf, wenn Graph-Zugriff besteht.channels.msteams.dangerouslyAllowNameMatching: Notfall-Schalter, um veränderbare UPN/Anzeigenamen-Abgleiche und direktes Team/Channel-Namens-Routing wieder zu aktivieren.channels.msteams.textChunkLimit: Größe der ausgehenden Text-Chunks.channels.msteams.chunkMode:length(Standard) odernewline, um bei Leerzeilen (Absatzgrenzen) zu trennen, bevor nach Länge gechunkt wird.channels.msteams.mediaAllowHosts: Allowlist für Hosts eingehender Anhänge (Standard sind Microsoft/Teams-Domains).channels.msteams.mediaAuthAllowHosts: Allowlist für das Anhängen von Authorization-Headern bei Media-Retries (Standard sind Graph + Bot Framework Hosts).channels.msteams.requireMention: Erfordert @Mention in Channels/Gruppen (Standard true).channels.msteams.replyStyle:thread | top-level(siehe Reply Style).channels.msteams.teams.<teamId>.replyStyle: Override pro Team.channels.msteams.teams.<teamId>.requireMention: Override pro Team.channels.msteams.teams.<teamId>.tools: Standard-Tool-Policy-Overrides pro Team (allow/deny/alsoAllow), wenn ein Channel-Override fehlt.channels.msteams.teams.<teamId>.toolsBySender: Standard-Tool-Policy-Overrides pro Team und Absender ("*"Wildcard unterstützt).channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: Override pro Channel.channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: Override pro Channel.channels.msteams.teams.<teamId>.channels.<conversationId>.tools: Tool-Policy-Overrides pro Channel (allow/deny/alsoAllow).channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: Tool-Policy-Overrides pro Channel und Absender ("*"Wildcard unterstützt).toolsBySenderKeys sollten explizite Präfixe nutzen:id:,e164:,username:,name:(alte Keys ohne Präfix werden weiterhin nur aufid:gemappt).channels.msteams.actions.memberInfo: Aktiviert oder deaktiviert die Graph-gestützte Member-Info-Aktion (Standard: aktiviert, wenn Graph-Zugangsdaten vorhanden sind).channels.msteams.sharePointSiteId: SharePoint Site-ID für Datei-Uploads in Gruppen-Chats/Channels (siehe Dateien in Gruppen-Chats senden).
Routing & Sessions
Abschnitt betitelt „Routing & Sessions“- Session-Keys folgen dem Standard-Agent-Format (siehe /concepts/session):
- Direktnachrichten teilen sich die Haupt-Session (
agent:<agentId>:<mainKey>). - Channel-/Gruppen-Nachrichten nutzen die Conversation-ID:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- Direktnachrichten teilen sich die Haupt-Session (
Antwort-Stil: Threads vs. Posts
Abschnitt betitelt „Antwort-Stil: Threads vs. Posts“Teams hat vor kurzem zwei UI-Styles für Channels eingeführt, die auf demselben Datenmodell basieren:
| Style | Beschreibung | Empfohlener replyStyle |
|---|---|---|
| Posts (klassisch) | Nachrichten erscheinen als Karten mit Antworten darunter | thread (Standard) |
| Threads (Slack-ähnlich) | Nachrichten fließen linear, ähnlich wie in Slack | top-level |
Das Problem: Die Teams API verrät nicht, welchen UI-Style ein Channel nutzt. Wenn du den falschen replyStyle verwendest:
threadin einem Channel im Threads-Stil → Antworten wirken seltsam verschachtelt.top-levelin einem Channel im Posts-Stil → Antworten erscheinen als separate Posts statt innerhalb eines Threads.
Lösung: Konfiguriere den replyStyle pro Channel, je nachdem, wie der Channel eingerichtet ist:
{ channels: { msteams: { replyStyle: "thread", teams: { "19:abc...@thread.tacv2": { channels: { "19:xyz...@thread.tacv2": { replyStyle: "top-level", }, }, }, }, }, },}Anhänge & Bilder
Abschnitt betitelt „Anhänge & Bilder“Aktuelle Einschränkungen:
- DMs: Bilder und Dateianhänge funktionieren über die Teams Bot File APIs.
- Channels/Gruppen: Anhänge werden im M365-Speicher (SharePoint/OneDrive) abgelegt. Der Webhook-Payload enthält nur einen HTML-Stub, nicht die eigentlichen Datei-Bytes. Graph API Berechtigungen sind erforderlich, um Channel-Anhänge herunterzuladen.
- Für das explizite Senden von Dateien nutzt du
action=upload-filezusammen mitmedia/filePath/path. Die optionalemessagewird zum begleitenden Text, undfilenameüberschreibt den Namen der hochgeladenen Datei. - Ohne Graph-Berechtigungen werden Channel-Nachrichten mit Bildern nur als reiner Text empfangen (der Bildinhalt ist für den Bot nicht zugänglich).
Standardmäßig lädt OpenClaw Medien nur von Microsoft/Teams-Hostnames herunter. Das kannst du mit channels.msteams.mediaAllowHosts überschreiben (nutze ["*"], um jeden Host zu erlauben). Authorization-Header werden nur an Hosts in channels.msteams.mediaAuthAllowHosts angehängt (Standard sind Graph + Bot Framework Hosts). Halte diese Liste strikt und vermeide Multi-Tenant-Suffixe.
Dateien in Gruppen-Chats senden
Abschnitt betitelt „Dateien in Gruppen-Chats senden“Bots können Dateien in DMs über den FileConsentCard-Flow senden, der bereits eingebaut ist. Das Senden von Dateien in Gruppen-Chats oder Channels erfordert jedoch ein zusätzliches Setup:
| Kontext | Wie Dateien gesendet werden | Erforderliches Setup |
|---|---|---|
| DMs | FileConsentCard → User akzeptiert → Bot-Upload | Funktioniert sofort |
| Gruppen-Chats/Channels | Upload zu SharePoint → Link teilen | Benötigt sharePointSiteId + Graph-Berechtigungen |
| Bilder (jeder Kontext) | Base64-kodiert inline | Funktioniert sofort |
Warum Gruppen-Chats SharePoint brauchen
Abschnitt betitelt „Warum Gruppen-Chats SharePoint brauchen“Bots besitzen kein persönliches OneDrive-Laufwerk (der /me/drive Graph API Endpunkt funktioniert nicht für Application-Identities). Um Dateien in Gruppen-Chats oder Channels zu senden, lädt der Bot diese auf eine SharePoint-Site hoch und erstellt einen Freigabelink.
-
Graph API Berechtigungen hinzufügen in Entra ID (Azure AD) → App Registration:
Sites.ReadWrite.All(Application) – Dateien in SharePoint hochladen.Chat.Read.All(Application) – optional, ermöglicht benutzerspezifische Freigabelinks.
-
Admin-Zustimmung erteilen für den Tenant.
-
Deine SharePoint Site ID abrufen:
Terminal-Fenster # 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" -
OpenClaw konfigurieren:
{channels: {msteams: {// ... other config ...sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",},},}
Freigabe-Verhalten
Abschnitt betitelt „Freigabe-Verhalten“| Berechtigung | Freigabe-Verhalten |
|---|---|
Nur Sites.ReadWrite.All | Organisationsweiter Link (jeder in der Org hat Zugriff) |
Sites.ReadWrite.All + Chat.Read.All | Benutzerspezifischer Link (nur Chat-Mitglieder haben Zugriff) |
Die benutzerspezifische Freigabe ist sicherer, da nur die Chat-Teilnehmer auf die Datei zugreifen können. Wenn die Chat.Read.All Berechtigung fehlt, nutzt der Bot automatisch die organisationsweite Freigabe.
Fallback-Verhalten
Abschnitt betitelt „Fallback-Verhalten“| Szenario | Ergebnis |
|---|---|
Gruppen-Chat + Datei + sharePointSiteId konfiguriert | Upload zu SharePoint, Senden des Freigabelinks |
Gruppen-Chat + Datei + keine sharePointSiteId | OneDrive-Upload-Versuch (kann scheitern), nur Text |
| Persönlicher Chat + Datei | FileConsentCard-Flow (funktioniert ohne SharePoint) |
| Beliebiger Kontext + Bild | Base64-kodiert inline (funktioniert ohne SharePoint) |
Speicherort der Dateien
Abschnitt betitelt „Speicherort der Dateien“Hochgeladene Dateien werden in einem Ordner /OpenClawShared/ in der Standard-Dokumentbibliothek der konfigurierten SharePoint-Site gespeichert.
Umfragen (Adaptive Cards)
Abschnitt betitelt „Umfragen (Adaptive Cards)“OpenClaw sendet Teams-Umfragen als Adaptive Cards, da es keine native Teams Poll API gibt.
- 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 zu erfassen.
- Umfragen posten aktuell noch keine automatischen Ergebniszusammenfassungen (prüfe bei Bedarf die Store-Datei).
Adaptive Cards (beliebig)
Abschnitt betitelt „Adaptive Cards (beliebig)“Sende beliebiges Adaptive Card JSON an Teams-Nutzer oder Unterhaltungen. Nutze dafür das message Tool oder das CLI.
Der Parameter card akzeptiert ein Adaptive Card JSON-Objekt. Wenn du card angibst, 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:abc...@thread.tacv2" \ --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}'Schau in die Adaptive Cards Dokumentation für das Card-Schema und Beispiele. Details zu den Zielformaten findest du unten im Abschnitt Zielformate.
Zielformate
Abschnitt betitelt „Zielformate“MSTeams-Ziele verwenden Präfixe, um zwischen Nutzern und Unterhaltungen zu unterscheiden:
| Zieltyp | Format | Beispiel |
|---|---|---|
| Nutzer (per ID) | user:<aad-object-id> | user:40a1a0ed-4ff2-4164-a219-55518990c197 |
| Nutzer (per Name) | user:<display-name> | user:John Smith (erfordert Graph API) |
| Gruppe/Kanal | conversation:<conversation-id> | conversation:19:abc123...@thread.tacv2 |
| Gruppe/Kanal (raw) | <conversation-id> | 19:abc123...@thread.tacv2 (wenn @thread enthält) |
CLI-Beispiele:
# Send to a user by IDopenclaw 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 channelopenclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello"
# Send an Adaptive Card to a conversationopenclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" \ --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:abc...@thread.tacv2", card: { type: "AdaptiveCard", version: "1.5", body: [{ type: "TextBlock", text: "Hello" }], },}Hinweis: Ohne das Präfix user: werden Namen standardmäßig als Gruppe oder Team aufgelöst. Verwende immer user:, wenn du Personen über ihren Anzeigenamen ansprichst.
Proaktives Messaging
Abschnitt betitelt „Proaktives Messaging“Proaktive Nachrichten sind erst möglich, nachdem ein Nutzer interagiert hat, da wir erst zu diesem Zeitpunkt die Conversation References speichern.
Schau dir /gateway/configuration an, um Details zu dmPolicy und dem Gating per Allowlist zu erfahren.
Team- und Channel-IDs (Häufiger Stolperstein)
Abschnitt betitelt „Team- und Channel-IDs (Häufiger Stolperstein)“Der groupId Query-Parameter in Teams-URLs ist NICHT die Team-ID, die du für die Konfiguration verwendest. Extrahiere die IDs stattdessen direkt aus dem URL-Pfad:
Team URL:
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=... └────────────────────────────┘ Team ID (URL-decode this)Channel 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-decoded, z. B.19:Bk4j...@thread.tacv2) - Channel-ID = Pfadsegment nach
/channel/(URL-decoded) - Ignoriere den
groupIdQuery-Parameter
Private Kanäle
Abschnitt betitelt „Private Kanäle“Bots haben in privaten Kanälen nur eingeschränkten Support:
| Feature | Standard-Kanäle | Private Kanäle |
|---|---|---|
| Bot-Installation | Ja | Eingeschränkt |
| Echtzeit-Nachrichten (Webhook) | Ja | Funktioniert evtl. nicht |
| RSC-Berechtigungen | Ja | Verhält sich evtl. anders |
| @mentions | Ja | Wenn Bot zugänglich ist |
| Graph API Verlauf | Ja | Ja (mit Berechtigungen) |
Workarounds, falls private Kanäle nicht funktionieren:
- Nutze Standard-Kanäle für Bot-Interaktionen.
- Nutze DMs – User können dem Bot immer direkt Nachrichten senden.
- Nutze die Graph API für den Zugriff auf den Verlauf (erfordert
ChannelMessage.Read.All).
Fehlerbehebung
Abschnitt betitelt „Fehlerbehebung“Häufige Probleme
Abschnitt betitelt „Häufige Probleme“- Bilder werden in Kanälen nicht angezeigt: Graph-Berechtigungen oder die Zustimmung des Admins fehlen. Installiere die Teams-App neu und beende Teams komplett, bevor du es neu startest.
- Keine Antworten im Kanal: Mentions sind standardmäßig erforderlich; setze
channels.msteams.requireMention=falseoder konfiguriere dies individuell pro Team/Kanal. - Versionskonflikt (Teams zeigt noch das alte Manifest): Entferne die App, füge sie neu hinzu und starte Teams vollständig neu, um den Cache zu aktualisieren.
- 401 Unauthorized vom Webhook: Das ist beim manuellen Testen ohne Azure JWT zu erwarten – es bedeutet, dass der Endpoint erreichbar ist, aber die Authentifizierung fehlgeschlagen ist. Nutze den Azure Web Chat für korrekte Tests.
Fehler beim Manifest-Upload
Abschnitt betitelt „Fehler beim Manifest-Upload“- “Icon file cannot be empty”: Das Manifest verweist auf 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 oder Chat installiert. Deinstalliere sie dort zuerst oder warte 5-10 Minuten, bis die Änderung systemweit übernommen wurde.
- “Something went wrong” beim Upload: Lade die App stattdessen über https://admin.teams.microsoft.com hoch. Öffne die Browser DevTools (F12) → Network-Tab und prüfe den Response Body auf die tatsächliche Fehlermeldung.
- Sideloading schlägt fehl: Versuche “App in den App-Katalog deiner Organisation hochladen” statt “Benutzerdefinierte App hochladen” – dies umgeht oft Sideload-Beschränkungen.
RSC-Berechtigungen funktionieren nicht
Abschnitt betitelt „RSC-Berechtigungen funktionieren nicht“- Prüfe, ob die
webApplicationInfo.idexakt mit der App ID deines Bots übereinstimmt. - Lade die App neu hoch und installiere sie im Team oder Chat neu.
- Kontrolliere, ob dein Organisations-Admin RSC-Berechtigungen blockiert hat.
- Bestätige, dass du den richtigen Scope verwendest:
ChannelMessage.Read.Groupfür Teams oderChatMessage.Read.Chatfür Gruppen-Chats.
Referenzen
Abschnitt betitelt „Referenzen“- Create Azure Bot — Azure Bot Setup-Guide
- Teams Developer Portal — Teams Apps erstellen und verwalten
- Teams app manifest schema
- Receive channel messages with RSC
- RSC permissions reference
- Teams bot file handling (Kanal/Gruppe erfordert Graph)
- Proactive messaging
Verwandte Themen
Abschnitt betitelt „Verwandte Themen“- Channels Overview — Übersicht aller unterstützten Channels
- Pairing — DM-Authentifizierung und Pairing-Flow
- Groups — Verhalten in Gruppen-Chats und Mention-Gating
- Channel Routing — Session-Routing für Nachrichten
- Security — Zugriffsmodell und Hardening
OpenClaw Expert
Noch festgefahren?
Wenn diese Seite nicht hilft, frage OpenClaw Expert nach Schritt-fuer-Schritt-Loesungen.