Zum Inhalt springen

Microsoft Teams Plugin für OpenClaw einrichten

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):

Terminal-Fenster
openclaw plugins install @openclaw/msteams

Lokaler Checkout (wenn du aus einem Git-Repo arbeitest):

Terminal-Fenster
openclaw plugins install ./path/to/local/msteams-plugin

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

Details: Plugins

  1. Installiere das Microsoft Teams Plugin.
  2. Erstelle einen Azure Bot (App ID + Client Secret + Tenant ID).
  3. Konfiguriere OpenClaw mit diesen Credentials.
  4. Gib /api/messages (Standard-Port 3978) über eine öffentliche URL oder einen Tunnel frei.
  5. 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).

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 } },
}

DM-Zugriff

  • Standardmäßig gilt: channels.msteams.dmPolicy = "pairing". Unbekannte Absender werden ignoriert, bis du sie bestätigst.
  • Für channels.msteams.allowFrom solltest 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: true aktiviert.
  • 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ügst groupAllowFrom hinzu). Nutze channels.defaults.groupPolicy, um den Standardwert zu überschreiben, falls nichts gesetzt ist.
  • channels.msteams.groupAllowFrom steuert, welche Absender Trigger in Gruppen-Chats oder Kanälen auslösen dürfen (greift als Fallback auf channels.msteams.allowFrom zurü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.teams auflistest.
  • 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: true ist aktiviert.

Beispiel:

{
channels: {
msteams: {
groupPolicy: "allowlist",
teams: {
"My Team": {
channels: {
General: { requireMention: true },
},
},
},
},
},
}
  1. Installiere das Microsoft Teams Plugin.
  2. Erstelle einen Azure Bot (App ID + Secret + Tenant ID).
  3. Erstelle ein Teams App Package, das auf den Bot verweist und die unten genannten RSC-Berechtigungen enthält.
  4. Lade die Teams App in ein Team hoch (oder installiere sie im persönlichen Bereich für DMs).
  5. Konfiguriere msteams in der ~/.openclaw/openclaw.json (oder über Umgebungsvariablen) und starte das Gateway.
  6. Das Gateway lauscht standardmäßig auf Bot Framework Webhook-Traffic unter /api/messages.

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

  1. Gehe zu Azure Bot erstellen

  2. Fülle den Reiter Grundlagen aus:

    FeldWert
    Bot handleDein Bot-Name, z. B. openclaw-msteams (muss eindeutig sein)
    SubscriptionWähle dein Azure-Abonnement aus
    Resource groupNeu erstellen oder vorhandene nutzen
    Pricing tierFree für Entwicklung/Tests
    Type of AppSingle Tenant (empfohlen - siehe Hinweis unten)
    Creation typeCreate 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.

  1. Klicke auf Review + create → Create (warte ca. 1-2 Minuten)
  1. Gehe zu deiner Azure Bot Ressource → Configuration
  2. Kopiere die Microsoft App ID → das ist deine appId
  3. Klicke auf Manage Password → du wirst zur App-Registrierung weitergeleitet
  4. Unter Certificates & secrets → New client secret → kopiere den Value → das ist dein appPassword
  5. Gehe zu Overview → kopiere die Directory (tenant) ID → das ist deine tenantId
  1. Im Azure Bot → Configuration
  2. Setze den Messaging endpoint auf deine Webhook-URL:
    • Produktion: https://deine-domain.com/api/messages
    • Lokale Entwicklung: Nutze einen Tunnel (siehe Lokale Entwicklung unten)
  1. Im Azure Bot → Channels
  2. Klicke auf Microsoft Teams → Configure → Save
  3. Akzeptiere die Nutzungsbedingungen

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

Option A: ngrok

Terminal-Fenster
ngrok http 3978
# Copy the https URL, e.g., https://abc123.ngrok.io
# Set messaging endpoint to: https://abc123.ngrok.io/api/messages

Option B: Tailscale Funnel

Terminal-Fenster
tailscale funnel 3978
# Use your Tailscale funnel URL as the messaging endpoint

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.

  1. Klicke auf + New app
  2. Gib die Basis-Infos ein (Name, Beschreibung, Entwickler-Infos)
  3. Gehe zu App features → Bot
  4. Wähle Enter a bot ID manually und füge deine Azure Bot App ID ein
  5. Prüfe die Scopes: Personal, Team, Group Chat
  6. Klicke auf Distribute → Download app package
  7. In Teams: Apps → Manage your apps → Upload a custom app → wähle das ZIP aus

Option A: Azure Web Chat (zuerst den Webhook prüfen)

  1. Im Azure Portal → deine Azure Bot Ressource → Test in Web Chat
  2. Sende eine Nachricht – du solltest eine Antwort erhalten
  3. Das bestätigt, dass dein Webhook-Endpunkt funktioniert, bevor du mit dem Teams-Setup weitermachst

Option B: Teams (nach der App-Installation)

  1. Installiere die Teams-App (Sideloading oder Organisationskatalog)
  2. Suche den Bot in Teams und sende eine DM
  3. Prüfe die Gateway-Logs auf eingehende Aktivitäten
  1. Installiere das Microsoft Teams Plugin

    • Über npm: openclaw plugins install @openclaw/msteams
    • Aus einem lokalen Verzeichnis: openclaw plugins install ./path/to/local/msteams-plugin
  2. Bot-Registrierung

    • Erstelle einen Azure Bot (siehe oben) und notiere dir:
      • App ID
      • Client secret (App-Passwort)
      • Tenant ID (single-tenant)
  3. Teams App Manifest

    • Füge einen bot-Eintrag mit botId = <App ID> hinzu.
    • Scopes: personal, team, groupChat.
    • supportsFiles: true (erforderlich für das Dateihandling im Personal Scope).
    • Füge RSC-Berechtigungen hinzu (siehe unten).
    • Erstelle Icons: outline.png (32x32) und color.png (192x192).
    • Packe alle drei Dateien in ein ZIP: manifest.json, outline.png, color.png.
  4. 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_ID
    • MSTEAMS_APP_PASSWORD
    • MSTEAMS_TENANT_ID
  5. Bot-Endpunkt

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

    • Der Teams-Channel startet automatisch, wenn das Plugin installiert ist und die msteams-Konfiguration mit den entsprechenden Zugangsdaten existiert.

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.Group RSC-Berechtigung (bereits im empfohlenen Manifest enthalten)
  • Für teamübergreifende Abfragen: User.Read.All Graph Application Berechtigung mit Admin-Zustimmung

Die Action wird über channels.msteams.actions.memberInfo gesteuert (standardmäßig aktiviert, wenn Graph-Zugangsdaten vorhanden sind).

  • channels.msteams.historyLimit steuert, wie viele aktuelle Nachrichten aus Kanälen oder Gruppen in den Prompt einfließen.
  • Falls nichts konfiguriert ist, greift messages.groupChat.historyLimit. Mit dem Wert 0 deaktivierst 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.dmHistoryLimit festlegen (User-Turns). Mit channels.msteams.dms["<user_id>"].historyLimit sind auch Overrides pro Nutzer möglich.

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 @mention
  • ChannelMessage.Send.Group (Application)
  • Member.Read.Group (Application)
  • Owner.Read.Group (Application)
  • ChannelSettings.Read.Group (Application)
  • TeamMember.Read.Group (Application)
  • TeamSettings.Read.Group (Application)

Für Gruppen-Chats:

  • ChatMessage.Read.Chat (Application) – alle Nachrichten in Gruppen-Chats empfangen, auch ohne @mention

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" },
],
},
},
}
  • bots[].botId muss exakt mit der Azure Bot App ID übereinstimmen.
  • webApplicationInfo.id muss ebenfalls der Azure Bot App ID entsprechen.
  • bots[].scopes muss die Bereiche abdecken, die du nutzen möchtest (personal, team, groupChat).
  • bots[].supportsFiles: true ist zwingend erforderlich, um Dateien im persönlichen Scope zu verarbeiten.
  • authorization.permissions.resourceSpecific muss Lese- und Schreibrechte für Kanäle enthalten, wenn du dort Traffic empfangen willst.

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

  1. Aktualisiere deine manifest.json mit den neuen Einstellungen.
  2. Erhöhe das version Feld (z. B. von 1.0.0 auf 1.1.0).
  3. Erstelle ein neues ZIP-Archiv mit dem Manifest und den Icons (manifest.json, outline.png, color.png).
  4. 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.
  5. Für Team-Kanäle: Installiere die App in jedem Team neu, damit die neuen Berechtigungen aktiv werden.
  6. Beende Teams komplett und starte es neu (nicht nur das Fenster schließen), um den Cache für App-Metadaten zu leeren.

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.
FunktionRSC-BerechtigungenGraph API
Echtzeit-NachrichtenJa (via Webhook)Nein (nur Polling)
Verlauf (Historie)NeinJa (Abfrage möglich)
Setup-AufwandNur App-ManifestErfordert Admin-Zustimmung + Token
Offline-BetriebNein (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.

  1. 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.All oder ChatMessage.Read.All (Gruppen-Chats)
  2. Erteile die Admin-Zustimmung für den Tenant.
  3. Erhöhe die Manifest-Version der Teams-App, lade sie neu hoch und installiere die App in Teams neu.
  4. 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.

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.

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)

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 (Standard 3978)
  • 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) oder newline, 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).
  • toolsBySender Keys sollten explizite Präfixe nutzen: id:, e164:, username:, name: (alte Keys ohne Präfix werden weiterhin nur auf id: 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).
  • 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>

Teams hat vor kurzem zwei UI-Styles für Channels eingeführt, die auf demselben Datenmodell basieren:

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

Das Problem: Die Teams API verrät nicht, welchen UI-Style ein Channel nutzt. Wenn du den falschen replyStyle verwendest:

  • thread in einem Channel im Threads-Stil → Antworten wirken seltsam verschachtelt.
  • top-level in 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",
},
},
},
},
},
},
}

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-file zusammen mit media / filePath / path. Die optionale message wird zum begleitenden Text, und filename ü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.

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:

KontextWie Dateien gesendet werdenErforderliches Setup
DMsFileConsentCard → User akzeptiert → Bot-UploadFunktioniert sofort
Gruppen-Chats/ChannelsUpload zu SharePoint → Link teilenBenötigt sharePointSiteId + Graph-Berechtigungen
Bilder (jeder Kontext)Base64-kodiert inlineFunktioniert sofort

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.

  1. 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.
  2. Admin-Zustimmung erteilen für den Tenant.

  3. 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"
  4. OpenClaw konfigurieren:

    {
    channels: {
    msteams: {
    // ... other config ...
    sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
    },
    },
    }
BerechtigungFreigabe-Verhalten
Nur Sites.ReadWrite.AllOrganisationsweiter Link (jeder in der Org hat Zugriff)
Sites.ReadWrite.All + Chat.Read.AllBenutzerspezifischer 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.

SzenarioErgebnis
Gruppen-Chat + Datei + sharePointSiteId konfiguriertUpload zu SharePoint, Senden des Freigabelinks
Gruppen-Chat + Datei + keine sharePointSiteIdOneDrive-Upload-Versuch (kann scheitern), nur Text
Persönlicher Chat + DateiFileConsentCard-Flow (funktioniert ohne SharePoint)
Beliebiger Kontext + BildBase64-kodiert inline (funktioniert ohne SharePoint)

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

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.json aufgezeichnet.
  • Das Gateway muss online bleiben, um Stimmen zu erfassen.
  • Umfragen posten aktuell noch keine automatischen Ergebniszusammenfassungen (prüfe bei Bedarf die Store-Datei).

AI Setup Assistant

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:

Terminal-Fenster
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.

MSTeams-Ziele verwenden Präfixe, um zwischen Nutzern und Unterhaltungen zu unterscheiden:

ZieltypFormatBeispiel
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/Kanalconversation:<conversation-id>conversation:19:abc123...@thread.tacv2
Gruppe/Kanal (raw)<conversation-id>19:abc123...@thread.tacv2 (wenn @thread enthält)

CLI-Beispiele:

Terminal-Fenster
# Send to a user by ID
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"
# Send to a user by display name (triggers Graph API lookup)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"
# Send to a group chat or channel
openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello"
# Send an Adaptive Card to a conversation
openclaw 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.

AI Setup Assistant

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.

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 groupId Query-Parameter

Bots haben in privaten Kanälen nur eingeschränkten Support:

FeatureStandard-KanälePrivate Kanäle
Bot-InstallationJaEingeschränkt
Echtzeit-Nachrichten (Webhook)JaFunktioniert evtl. nicht
RSC-BerechtigungenJaVerhält sich evtl. anders
@mentionsJaWenn Bot zugänglich ist
Graph API VerlaufJaJa (mit Berechtigungen)

Workarounds, falls private Kanäle nicht funktionieren:

  1. Nutze Standard-Kanäle für Bot-Interaktionen.
  2. Nutze DMs – User können dem Bot immer direkt Nachrichten senden.
  3. Nutze die Graph API für den Zugriff auf den Verlauf (erfordert ChannelMessage.Read.All).
  • 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=false oder 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.
  • “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ür color.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.
  1. Prüfe, ob die webApplicationInfo.id exakt mit der App ID deines Bots übereinstimmt.
  2. Lade die App neu hoch und installiere sie im Team oder Chat neu.
  3. Kontrolliere, ob dein Organisations-Admin RSC-Berechtigungen blockiert hat.
  4. Bestätige, dass du den richtigen Scope verwendest: ChannelMessage.Read.Group für Teams oder ChatMessage.Read.Chat für Gruppen-Chats.
  • 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

AI Setup Assistant

OpenClaw

OpenClaw Expert

Noch festgefahren?

Wenn diese Seite nicht hilft, frage OpenClaw Expert nach Schritt-fuer-Schritt-Loesungen.