Mainstream messaging
Microsoft Teams
Status: obsługiwane są tekst i załączniki w DM; wysyłanie plików w kanałach/grupach wymaga sharePointSiteId + uprawnień Graph (zobacz Wysyłanie plików w czatach grupowych). Ankiety są wysyłane przez Adaptive Cards. Akcje wiadomości udostępniają jawne upload-file dla wysyłek, w których plik jest pierwszy.
Dołączony Plugin
Microsoft Teams jest dostarczany jako dołączony Plugin w bieżących wydaniach OpenClaw, więc w normalnej wersji pakietowej nie jest wymagana osobna instalacja.
Jeśli używasz starszej wersji lub instalacji niestandardowej, która wyklucza dołączony Teams, zainstaluj pakiet npm bezpośrednio:
openclaw plugins install @openclaw/msteams
Użyj samego pakietu, aby śledzić bieżący oficjalny tag wydania. Przypinaj dokładną wersję tylko wtedy, gdy potrzebujesz powtarzalnej instalacji.
Lokalny checkout (podczas uruchamiania z repozytorium git):
openclaw plugins install ./path/to/local/msteams-plugin
Szczegóły: Pluginy
Szybka konfiguracja
@microsoft/teams.cli obsługuje rejestrację bota, tworzenie manifestu i generowanie poświadczeń jednym poleceniem.
1. Zainstaluj i zaloguj się
npm install -g @microsoft/teams.cli@preview
teams login
teams status # verify you're logged in and see your tenant info
2. Uruchom tunel (Teams nie może połączyć się z localhost)
Zainstaluj i uwierzytelnij devtunnel CLI, jeśli jeszcze tego nie zrobiono (przewodnik wprowadzający).
# One-time setup (persistent URL across sessions):
devtunnel create my-openclaw-bot --allow-anonymous
devtunnel port create my-openclaw-bot -p 3978 --protocol auto
# Each dev session:
devtunnel host my-openclaw-bot
# Your endpoint: https://<tunnel-id>.devtunnels.ms/api/messages
Alternatywy: ngrok http 3978 lub tailscale funnel 3978 (ale mogą one zmieniać adresy URL w każdej sesji).
3. Utwórz aplikację
teams app create \
--name "OpenClaw" \
--endpoint "https://<your-tunnel-url>/api/messages"
To pojedyncze polecenie:
- Tworzy aplikację Entra ID (Azure AD)
- Generuje sekret klienta
- Buduje i przesyła manifest aplikacji Teams (z ikonami)
- Rejestruje bota (domyślnie zarządzanego przez Teams - subskrypcja Azure nie jest potrzebna)
Dane wyjściowe pokażą CLIENT_ID, CLIENT_SECRET, TENANT_ID i Teams App ID - zanotuj je na potrzeby kolejnych kroków. Polecenie zaproponuje też bezpośrednią instalację aplikacji w Teams.
4. Skonfiguruj OpenClaw przy użyciu poświadczeń z danych wyjściowych:
{
channels: {
msteams: {
enabled: true,
appId: "<CLIENT_ID>",
appPassword: "<CLIENT_SECRET>",
tenantId: "<TENANT_ID>",
webhook: { port: 3978, path: "/api/messages" },
},
},
}
Albo użyj bezpośrednio zmiennych środowiskowych: MSTEAMS_APP_ID, MSTEAMS_APP_PASSWORD, MSTEAMS_TENANT_ID.
5. Zainstaluj aplikację w Teams
teams app create poprosi o instalację aplikacji - wybierz „Install in Teams”. Jeśli ten krok został pominięty, możesz później uzyskać link:
teams app get <teamsAppId> --install-link
6. Sprawdź, czy wszystko działa
teams app doctor <teamsAppId>
Uruchamia to diagnostykę rejestracji bota, konfiguracji aplikacji AAD, poprawności manifestu i konfiguracji SSO.
W przypadku wdrożeń produkcyjnych rozważ użycie uwierzytelniania federacyjnego (certyfikatu lub tożsamości zarządzanej) zamiast sekretów klienta.
Cele
- Rozmawiaj z OpenClaw przez DM, czaty grupowe lub kanały w Teams.
- Zachowaj deterministyczne routowanie: odpowiedzi zawsze wracają do kanału, z którego przyszły.
- Domyślnie używaj bezpiecznego zachowania kanału (wzmianki wymagane, chyba że skonfigurowano inaczej).
Zapisy konfiguracji
Domyślnie Microsoft Teams może zapisywać aktualizacje konfiguracji wyzwalane przez /config set|unset (wymaga commands.config: true).
Wyłącz za pomocą:
{
channels: { msteams: { configWrites: false } },
}
Kontrola dostępu (DM + grupy)
Dostęp DM
- Domyślnie:
channels.msteams.dmPolicy = "pairing". Nieznani nadawcy są ignorowani do czasu zatwierdzenia. channels.msteams.allowFrompowinno używać stabilnych identyfikatorów obiektów AAD.- Nie polegaj na dopasowywaniu UPN/nazwy wyświetlanej dla list dozwolonych - mogą się zmienić. OpenClaw domyślnie wyłącza bezpośrednie dopasowywanie nazw; włącz je jawnie za pomocą
channels.msteams.dangerouslyAllowNameMatching: true. - Kreator może rozwiązywać nazwy na identyfikatory przez Microsoft Graph, gdy pozwalają na to poświadczenia.
Dostęp grupowy
- Domyślnie:
channels.msteams.groupPolicy = "allowlist"(zablokowane, chyba że dodaszgroupAllowFrom). Użyjchannels.defaults.groupPolicy, aby nadpisać wartość domyślną, gdy nie jest ustawiona. channels.msteams.groupAllowFromkontroluje, którzy nadawcy mogą wyzwalać działania w czatach grupowych/kanałach (z wartością zapasowąchannels.msteams.allowFrom).- Ustaw
groupPolicy: "open", aby zezwolić dowolnemu członkowi (domyślnie nadal z bramką wzmianki). - Aby nie zezwalać na żadne kanały, ustaw
channels.msteams.groupPolicy: "disabled".
Przykład:
{
channels: {
msteams: {
groupPolicy: "allowlist",
groupAllowFrom: ["[email protected]"],
},
},
}
Teams + lista dozwolonych kanałów
- Ogranicz odpowiedzi grup/kanałów, wyliczając zespoły i kanały w
channels.msteams.teams. - Klucze powinny używać stabilnych identyfikatorów konwersacji Teams z linków Teams, a nie zmiennych nazw wyświetlanych.
- Gdy
groupPolicy="allowlist"i obecna jest lista dozwolonych zespołów, akceptowane są tylko wymienione zespoły/kanały (z bramką wzmianki). - Kreator konfiguracji przyjmuje wpisy
Team/Channeli zapisuje je za Ciebie. - Podczas uruchamiania OpenClaw rozwiązuje nazwy zespołów/kanałów i użytkowników z listy dozwolonych na identyfikatory (gdy pozwalają na to uprawnienia Graph)
i zapisuje mapowanie w logach; nierozwiązane nazwy zespołów/kanałów są zachowywane tak, jak wpisano, ale domyślnie ignorowane przy routowaniu, chyba że włączono
channels.msteams.dangerouslyAllowNameMatching: true.
Przykład:
{
channels: {
msteams: {
groupPolicy: "allowlist",
teams: {
"My Team": {
channels: {
General: { requireMention: true },
},
},
},
},
},
}
Konfiguracja ręczna (bez Teams CLI)
Jeśli nie możesz użyć Teams CLI, możesz skonfigurować bota ręcznie przez Azure Portal.
Jak to działa
- Upewnij się, że Plugin Microsoft Teams jest dostępny (dołączony w bieżących wydaniach).
- Utwórz Azure Bot (App ID + sekret + identyfikator dzierżawy).
- Zbuduj pakiet aplikacji Teams, który odwołuje się do bota i zawiera poniższe uprawnienia RSC.
- Prześlij/zainstaluj aplikację Teams w zespole (lub w zakresie osobistym dla DM).
- Skonfiguruj
msteamsw~/.openclaw/openclaw.json(lub zmiennych środowiskowych) i uruchom Gateway. - Gateway domyślnie nasłuchuje ruchu Webhook Bot Framework na
/api/messages.
Krok 1: Utwórz Azure Bot
-
Przejdź do Utwórz Azure Bot
-
Wypełnij kartę Podstawy:
Pole Wartość Uchwyt bota Nazwa bota, np. openclaw-msteams(musi być unikatowa)Subskrypcja Wybierz swoją subskrypcję Azure Grupa zasobów Utwórz nową albo użyj istniejącej Warstwa cenowa Free do tworzenia/testowania Typ aplikacji Single Tenant (zalecane - zobacz uwagę poniżej) Typ tworzenia Create new Microsoft App ID
- Kliknij Review + create → Create (poczekaj około 1-2 minuty)
Krok 2: Pobierz poświadczenia
- Przejdź do zasobu Azure Bot → Configuration
- Skopiuj Microsoft App ID → to jest Twój
appId - Kliknij Manage Password → przejdź do App Registration
- W sekcji Certificates & secrets → New client secret → skopiuj Value → to jest Twój
appPassword - Przejdź do Overview → skopiuj Directory (tenant) ID → to jest Twój
tenantId
Krok 3: Skonfiguruj Messaging Endpoint
- W Azure Bot → Configuration
- Ustaw Messaging endpoint na adres URL Webhook:
- Produkcja:
https://your-domain.com/api/messages - Lokalne tworzenie: użyj tunelu (zobacz Lokalne tworzenie poniżej)
- Produkcja:
Krok 4: Włącz kanał Teams
- W Azure Bot → Channels
- Kliknij Microsoft Teams → Configure → Save
- Zaakceptuj Terms of Service
Krok 5: Zbuduj manifest aplikacji Teams
- Dołącz wpis
botzbotId = <App ID>. - Zakresy:
personal,team,groupChat. supportsFiles: true(wymagane do obsługi plików w zakresie osobistym).- Dodaj uprawnienia RSC (zobacz Uprawnienia RSC).
- Utwórz ikony:
outline.png(32x32) icolor.png(192x192). - Spakuj wszystkie trzy pliki razem:
manifest.json,outline.png,color.png.
Krok 6: Skonfiguruj OpenClaw
{
channels: {
msteams: {
enabled: true,
appId: "<APP_ID>",
appPassword: "<APP_PASSWORD>",
tenantId: "<TENANT_ID>",
webhook: { port: 3978, path: "/api/messages" },
},
},
}
Zmienne środowiskowe: MSTEAMS_APP_ID, MSTEAMS_APP_PASSWORD, MSTEAMS_TENANT_ID.
Krok 7: Uruchom Gateway
Kanał Teams uruchamia się automatycznie, gdy Plugin jest dostępny i istnieje konfiguracja msteams z poświadczeniami.
Uwierzytelnianie federacyjne (certyfikat plus tożsamość zarządzana)
Dodano w 2026.4.11
W przypadku wdrożeń produkcyjnych OpenClaw obsługuje uwierzytelnianie federacyjne jako bezpieczniejszą alternatywę dla sekretów klienta. Dostępne są dwie metody:
Opcja A: Uwierzytelnianie oparte na certyfikacie
Użyj certyfikatu PEM zarejestrowanego w rejestracji aplikacji Entra ID.
Konfiguracja:
- Wygeneruj lub uzyskaj certyfikat (format PEM z kluczem prywatnym).
- W Entra ID → App Registration → Certificates & secrets → Certificates → prześlij certyfikat publiczny.
Konfiguracja:
{
channels: {
msteams: {
enabled: true,
appId: "<APP_ID>",
tenantId: "<TENANT_ID>",
authType: "federated",
certificatePath: "/path/to/cert.pem",
webhook: { port: 3978, path: "/api/messages" },
},
},
}
Zmienne środowiskowe:
MSTEAMS_AUTH_TYPE=federatedMSTEAMS_CERTIFICATE_PATH=/path/to/cert.pem
Opcja B: Azure Managed Identity
Użyj Azure Managed Identity do uwierzytelniania bez hasła. To idealne rozwiązanie dla wdrożeń w infrastrukturze Azure (AKS, App Service, maszyny wirtualne Azure), gdzie dostępna jest tożsamość zarządzana.
Jak to działa:
- Pod/maszyna wirtualna bota ma tożsamość zarządzaną (przypisaną przez system lub przypisaną przez użytkownika).
- Poświadczenie tożsamości federacyjnej łączy tożsamość zarządzaną z rejestracją aplikacji Entra ID.
- W czasie działania OpenClaw używa
@azure/identity, aby uzyskać tokeny z punktu końcowego Azure IMDS (169.254.169.254). - Token jest przekazywany do Teams SDK w celu uwierzytelnienia bota.
Wymagania wstępne:
- Infrastruktura Azure z włączoną tożsamością zarządzaną (tożsamość obciążenia AKS, App Service, maszyna wirtualna)
- Poświadczenie tożsamości federacyjnej utworzone w rejestracji aplikacji Entra ID
- Dostęp sieciowy do IMDS (
169.254.169.254:80) z poda/maszyny wirtualnej
Konfiguracja (tożsamość zarządzana przypisana przez system):
{
channels: {
msteams: {
enabled: true,
appId: "<APP_ID>",
tenantId: "<TENANT_ID>",
authType: "federated",
useManagedIdentity: true,
webhook: { port: 3978, path: "/api/messages" },
},
},
}
Konfiguracja (zarządzana tożsamość przypisana przez użytkownika):
{
channels: {
msteams: {
enabled: true,
appId: "<APP_ID>",
tenantId: "<TENANT_ID>",
authType: "federated",
useManagedIdentity: true,
managedIdentityClientId: "<MI_CLIENT_ID>",
webhook: { port: 3978, path: "/api/messages" },
},
},
}
Zmienne środowiskowe:
MSTEAMS_AUTH_TYPE=federatedMSTEAMS_USE_MANAGED_IDENTITY=trueMSTEAMS_MANAGED_IDENTITY_CLIENT_ID=<client-id>(tylko dla tożsamości przypisanej przez użytkownika)
Konfiguracja AKS Workload Identity
Dla wdrożeń AKS używających tożsamości obciążenia:
-
Włącz tożsamość obciążenia w swoim klastrze AKS.
-
Utwórz poświadczenie tożsamości federacyjnej w rejestracji aplikacji Entra ID:
az ad app federated-credential create --id <APP_OBJECT_ID> --parameters '{ "name": "my-bot-workload-identity", "issuer": "<AKS_OIDC_ISSUER_URL>", "subject": "system:serviceaccount:<NAMESPACE>:<SERVICE_ACCOUNT>", "audiences": ["api://AzureADTokenExchange"] }' -
Dodaj adnotację do konta usługi Kubernetes z identyfikatorem klienta aplikacji:
apiVersion: v1 kind: ServiceAccount metadata: name: my-bot-sa annotations: azure.workload.identity/client-id: "<APP_CLIENT_ID>" -
Oznacz pod etykietą na potrzeby wstrzykiwania tożsamości obciążenia:
metadata: labels: azure.workload.identity/use: "true" -
Zapewnij dostęp sieciowy do IMDS (
169.254.169.254) - jeśli używasz NetworkPolicy, dodaj regułę ruchu wychodzącego zezwalającą na ruch do169.254.169.254/32na porcie 80.
Porównanie typów uwierzytelniania
| Metoda | Konfiguracja | Zalety | Wady |
|---|---|---|---|
| Sekret klienta | appPassword |
Prosta konfiguracja | Wymagana rotacja sekretu, mniejsze bezpieczeństwo |
| Certyfikat | authType: "federated" + certificatePath |
Brak współdzielonego sekretu w sieci | Narzut związany z zarządzaniem certyfikatami |
| Tożsamość zarządzana | authType: "federated" + useManagedIdentity |
Bez haseł, brak sekretów do zarządzania | Wymagana infrastruktura Azure |
Domyślne zachowanie: Gdy authType nie jest ustawione, OpenClaw domyślnie używa uwierzytelniania za pomocą sekretu klienta. Istniejące konfiguracje nadal działają bez zmian.
Programowanie lokalne (tunelowanie)
Teams nie może uzyskać dostępu do localhost. Użyj trwałego tunelu deweloperskiego, aby Twój URL pozostawał taki sam między sesjami:
# Jednorazowa konfiguracja:
devtunnel create my-openclaw-bot --allow-anonymous
devtunnel port create my-openclaw-bot -p 3978 --protocol auto
# Każda sesja deweloperska:
devtunnel host my-openclaw-bot
Alternatywy: ngrok http 3978 lub tailscale funnel 3978 (adresy URL mogą zmieniać się w każdej sesji).
Jeśli URL tunelu się zmieni, zaktualizuj punkt końcowy:
teams app update <teamsAppId> --endpoint "https://<new-url>/api/messages"
Testowanie bota
Uruchom diagnostykę:
teams app doctor <teamsAppId>
Sprawdza rejestrację bota, aplikację AAD, manifest i konfigurację SSO w jednym przebiegu.
Wyślij wiadomość testową:
- Zainstaluj aplikację Teams (użyj linku instalacyjnego z
teams app get <id> --install-link) - Znajdź bota w Teams i wyślij wiadomość prywatną
- Sprawdź logi Gateway pod kątem przychodzącej aktywności
Zmienne środowiskowe
Wszystkie klucze konfiguracji można zamiast tego ustawić za pomocą zmiennych środowiskowych:
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_IDMSTEAMS_AUTH_TYPE(opcjonalnie:"secret"lub"federated")MSTEAMS_CERTIFICATE_PATH(federacyjny + certyfikat)MSTEAMS_CERTIFICATE_THUMBPRINT(opcjonalnie, niewymagane do uwierzytelniania)MSTEAMS_USE_MANAGED_IDENTITY(federacyjny + tożsamość zarządzana)MSTEAMS_MANAGED_IDENTITY_CLIENT_ID(tylko MI przypisana przez użytkownika)
Akcja informacji o członku
OpenClaw udostępnia opartą na Graph akcję member-info dla Microsoft Teams, aby agenci i automatyzacje mogły pobierać szczegóły członków kanału (nazwę wyświetlaną, adres e-mail, rolę) bezpośrednio z Microsoft Graph.
Wymagania:
- Uprawnienie RSC
Member.Read.Group(już w zalecanym manifeście) - Dla wyszukiwań między zespołami: uprawnienie aplikacji Graph
User.Read.Allze zgodą administratora
Akcja jest kontrolowana przez channels.msteams.actions.memberInfo (domyślnie: włączona, gdy dostępne są poświadczenia Graph).
Kontekst historii
channels.msteams.historyLimitkontroluje, ile ostatnich wiadomości kanału/grupy jest dołączanych do promptu.- W razie braku wartości używa
messages.groupChat.historyLimit. Ustaw0, aby wyłączyć (domyślnie 50). - Pobrana historia wątku jest filtrowana według list dozwolonych nadawców (
allowFrom/groupAllowFrom), więc inicjowanie kontekstu wątku obejmuje tylko wiadomości od dozwolonych nadawców. - Kontekst cytowanych załączników (
ReplyTo*wyprowadzony z HTML odpowiedzi Teams) jest obecnie przekazywany w otrzymanej postaci. - Innymi słowy, listy dozwolonych nadawców kontrolują, kto może uruchomić agenta; obecnie filtrowane są tylko określone ścieżki kontekstu uzupełniającego.
- Historię DM można ograniczyć za pomocą
channels.msteams.dmHistoryLimit(tury użytkownika). Nadpisania dla poszczególnych użytkowników:channels.msteams.dms["<user_id>"].historyLimit.
Bieżące uprawnienia RSC Teams (manifest)
To są istniejące uprawnienia resourceSpecific w naszym manifeście aplikacji Teams. Obowiązują tylko w zespole/czacie, w którym aplikacja jest zainstalowana.
Dla kanałów (zakres zespołu):
ChannelMessage.Read.Group(Application) - odbieranie wszystkich wiadomości kanału bez @wzmiankiChannelMessage.Send.Group(Application)Member.Read.Group(Application)Owner.Read.Group(Application)ChannelSettings.Read.Group(Application)TeamMember.Read.Group(Application)TeamSettings.Read.Group(Application)
Dla czatów grupowych:
ChatMessage.Read.Chat(Application) - odbieranie wszystkich wiadomości czatu grupowego bez @wzmianki
Aby dodać uprawnienia RSC przez Teams CLI:
teams app rsc add <teamsAppId> ChannelMessage.Read.Group --type Application
Przykładowy manifest Teams (zredagowany)
Minimalny, prawidłowy przykład z wymaganymi polami. Zastąp identyfikatory i adresy URL.
{
$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" },
],
},
},
}
Zastrzeżenia dotyczące manifestu (pola wymagane)
bots[].botIdmusi pasować do identyfikatora aplikacji Azure Bot.webApplicationInfo.idmusi pasować do identyfikatora aplikacji Azure Bot.bots[].scopesmusi zawierać powierzchnie, których planujesz używać (personal,team,groupChat).bots[].supportsFiles: truejest wymagane do obsługi plików w zakresie osobistym.authorization.permissions.resourceSpecificmusi zawierać odczyt/wysyłanie kanału, jeśli chcesz obsługiwać ruch kanału.
Aktualizowanie istniejącej aplikacji
Aby zaktualizować już zainstalowaną aplikację Teams (np. dodać uprawnienia RSC):
# Pobierz, edytuj i ponownie prześlij manifest
teams app manifest download <teamsAppId> manifest.json
# Edytuj manifest.json lokalnie...
teams app manifest upload manifest.json <teamsAppId>
# Wersja zostanie automatycznie podbita, jeśli zawartość się zmieniła
Po aktualizacji zainstaluj ponownie aplikację w każdym zespole, aby nowe uprawnienia zaczęły obowiązywać, oraz całkowicie zamknij i ponownie uruchom Teams (nie tylko zamknij okno), aby wyczyścić pamięć podręczną metadanych aplikacji.
Ręczna aktualizacja manifestu (bez CLI)
- Zaktualizuj swój
manifest.jsonnowymi ustawieniami - Zwiększ wartość pola
version(np.1.0.0→1.1.0) - Ponownie spakuj manifest z ikonami (
manifest.json,outline.png,color.png) - Prześlij nowy plik zip:
- Centrum administracyjne Teams: Aplikacje Teams → Zarządzaj aplikacjami → znajdź swoją aplikację → Prześlij nową wersję
- Instalacja boczna: W Teams → Aplikacje → Zarządzaj swoimi aplikacjami → Przekaż aplikację niestandardową
Możliwości: tylko RSC vs Graph
Z tylko Teams RSC (aplikacja zainstalowana, bez uprawnień Graph API)
Działa:
- Odczyt tekstu wiadomości kanału.
- Wysyłanie tekstu wiadomości kanału.
- Odbieranie załączników plików w osobistych (DM) rozmowach.
Nie działa:
- Zawartość obrazów lub plików w kanałach/grupach (ładunek zawiera tylko zaślepkę HTML).
- Pobieranie załączników przechowywanych w SharePoint/OneDrive.
- Odczyt historii wiadomości (poza zdarzeniem Webhook na żywo).
Z Teams RSC + uprawnieniami aplikacji Microsoft Graph
Dodaje:
- Pobieranie hostowanych treści (obrazów wklejonych do wiadomości).
- Pobieranie załączników plików przechowywanych w SharePoint/OneDrive.
- Odczyt historii wiadomości kanału/czatu przez Graph.
RSC vs Graph API
| Możliwość | Uprawnienia RSC | Graph API |
|---|---|---|
| Wiadomości w czasie rzeczywistym | Tak (przez Webhook) | Nie (tylko odpytywanie) |
| Wiadomości historyczne | Nie | Tak (może odpytywać historię) |
| Złożoność konfiguracji | Tylko manifest aplikacji | Wymaga zgody administratora + przepływu tokenu |
| Działa offline | Nie (musi działać) | Tak (zapytania w dowolnym momencie) |
Najważniejsze: RSC służy do nasłuchiwania w czasie rzeczywistym; Graph API służy do dostępu historycznego. Aby nadrobić pominięte wiadomości podczas pracy offline, potrzebujesz Graph API z ChannelMessage.Read.All (wymaga zgody administratora).
Multimedia i historia z włączonym Graph (wymagane dla kanałów)
Jeśli potrzebujesz obrazów/plików w kanałach albo chcesz pobierać historię wiadomości, musisz włączyć uprawnienia Microsoft Graph i udzielić zgody administratora.
- W Entra ID (Azure AD) Rejestracja aplikacji dodaj uprawnienia aplikacji Microsoft Graph:
ChannelMessage.Read.All(załączniki kanału + historia)Chat.Read.AlllubChatMessage.Read.All(czaty grupowe)
- Udziel zgody administratora dla dzierżawy.
- Podbij wersję manifestu aplikacji Teams, prześlij go ponownie i zainstaluj ponownie aplikację w Teams.
- Całkowicie zamknij i ponownie uruchom Teams, aby wyczyścić pamięć podręczną metadanych aplikacji.
Dodatkowe uprawnienie dla wzmianek użytkowników: @wzmianki o użytkownikach działają od razu dla użytkowników w rozmowie. Jeśli jednak chcesz dynamicznie wyszukiwać i wspominać użytkowników, którzy nie są w bieżącej rozmowie, dodaj uprawnienie User.Read.All (Application) i udziel zgody administratora.
Znane ograniczenia
Limity czasu Webhook
Teams dostarcza wiadomości przez Webhook HTTP. Jeśli przetwarzanie trwa zbyt długo (np. powolne odpowiedzi LLM), możesz zobaczyć:
- Limity czasu Gateway
- Ponawianie wiadomości przez Teams (powodujące duplikaty)
- Porzucone odpowiedzi
OpenClaw obsługuje to, szybko zwracając odpowiedź i wysyłając odpowiedzi proaktywnie, ale bardzo wolne odpowiedzi nadal mogą powodować problemy.
Formatowanie
Markdown Teams jest bardziej ograniczony niż w Slack lub Discord:
- Podstawowe formatowanie działa: pogrubienie, kursywa,
code, linki - Złożony Markdown (tabele, zagnieżdżone listy) może nie renderować się poprawnie
- Adaptive Cards są obsługiwane dla ankiet i wysyłek prezentacji semantycznych (zobacz poniżej)
Konfiguracja
Kluczowe ustawienia (zobacz /gateway/configuration dla współdzielonych wzorców kanałów):
channels.msteams.enabled: włącz/wyłącz kanał.channels.msteams.appId,channels.msteams.appPassword,channels.msteams.tenantId: dane uwierzytelniające bota.channels.msteams.webhook.port(domyślnie3978)channels.msteams.webhook.path(domyślnie/api/messages)channels.msteams.dmPolicy:pairing | allowlist | open | disabled(domyślnie: pairing)channels.msteams.allowFrom: lista dozwolonych nadawców DM (zalecane identyfikatory obiektów AAD). Kreator rozwiązuje nazwy na identyfikatory podczas konfiguracji, gdy dostęp do Graph jest dostępny.channels.msteams.dangerouslyAllowNameMatching: przełącznik awaryjny ponownie włączający dopasowywanie zmiennych UPN/nazw wyświetlanych oraz bezpośrednie kierowanie po nazwie zespołu/kanału.channels.msteams.textChunkLimit: rozmiar fragmentu tekstu wychodzącego.channels.msteams.chunkMode:length(domyślnie) lubnewline, aby dzielić według pustych linii (granic akapitów) przed dzieleniem według długości.channels.msteams.mediaAllowHosts: lista dozwolonych hostów dla załączników przychodzących (domyślnie domeny Microsoft/Teams).channels.msteams.mediaAuthAllowHosts: lista dozwolonych hostów do dołączania nagłówków Authorization przy ponownych próbach pobierania multimediów (domyślnie hosty Graph + Bot Framework).channels.msteams.requireMention: wymagaj @wzmianki w kanałach/grupach (domyślnie true).channels.msteams.replyStyle:thread | top-level(zobacz Styl odpowiedzi).channels.msteams.teams.<teamId>.replyStyle: nadpisanie dla zespołu.channels.msteams.teams.<teamId>.requireMention: nadpisanie dla zespołu.channels.msteams.teams.<teamId>.tools: domyślne nadpisania zasad narzędzi dla zespołu (allow/deny/alsoAllow) używane, gdy brakuje nadpisania kanału.channels.msteams.teams.<teamId>.toolsBySender: domyślne nadpisania zasad narzędzi dla zespołu i nadawcy (obsługiwany symbol wieloznaczny"*").channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: nadpisanie dla kanału.channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: nadpisanie dla kanału.channels.msteams.teams.<teamId>.channels.<conversationId>.tools: nadpisania zasad narzędzi dla kanału (allow/deny/alsoAllow).channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: nadpisania zasad narzędzi dla kanału i nadawcy (obsługiwany symbol wieloznaczny"*").- Klucze
toolsBySenderpowinny używać jawnych prefiksów:id:,e164:,username:,name:(starsze klucze bez prefiksu nadal mapują tylko naid:). channels.msteams.actions.memberInfo: włącz lub wyłącz akcję informacji o członku opartą na Graph (domyślnie: włączona, gdy dostępne są dane uwierzytelniające Graph).channels.msteams.authType: typ uwierzytelniania -"secret"(domyślnie) lub"federated".channels.msteams.certificatePath: ścieżka do pliku certyfikatu PEM (tryb federacyjny + uwierzytelnianie certyfikatem).channels.msteams.certificateThumbprint: odcisk palca certyfikatu (opcjonalny, niewymagany do uwierzytelniania).channels.msteams.useManagedIdentity: włącz uwierzytelnianie tożsamością zarządzaną (tryb federacyjny).channels.msteams.managedIdentityClientId: identyfikator klienta dla tożsamości zarządzanej przypisanej przez użytkownika.channels.msteams.sharePointSiteId: identyfikator witryny SharePoint do przesyłania plików w czatach grupowych/kanałach (zobacz Wysyłanie plików w czatach grupowych).
Routing i sesje
- Klucze sesji używają standardowego formatu agenta (zobacz /concepts/session):
- Wiadomości bezpośrednie współdzielą główną sesję (
agent:<agentId>:<mainKey>). - Wiadomości kanału/grupy używają identyfikatora konwersacji:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- Wiadomości bezpośrednie współdzielą główną sesję (
Styl odpowiedzi: wątki kontra posty
Teams niedawno wprowadził dwa style interfejsu kanału na tym samym bazowym modelu danych:
| Styl | Opis | Zalecane replyStyle |
|---|---|---|
| Posty (klasyczne) | Wiadomości pojawiają się jako karty z odpowiedziami w wątku pod spodem | thread (domyślnie) |
| Wątki (jak w Slack) | Wiadomości płyną liniowo, bardziej jak w Slack | top-level |
Problem: API Teams nie ujawnia, którego stylu interfejsu używa kanał. Jeśli użyjesz niewłaściwego replyStyle:
threadw kanale w stylu Wątków → odpowiedzi pojawiają się niezgrabnie zagnieżdżonetop-levelw kanale w stylu Postów → odpowiedzi pojawiają się jako osobne posty najwyższego poziomu zamiast w wątku
Rozwiązanie: Skonfiguruj replyStyle dla każdego kanału na podstawie tego, jak kanał jest ustawiony:
{
channels: {
msteams: {
replyStyle: "thread",
teams: {
"19:[email protected]": {
channels: {
"19:[email protected]": {
replyStyle: "top-level",
},
},
},
},
},
},
}
Załączniki i obrazy
Obecne ograniczenia:
- DM-y: Obrazy i załączniki plików działają przez API plików bota Teams.
- Kanały/grupy: Załączniki znajdują się w magazynie M365 (SharePoint/OneDrive). Ładunek webhooka zawiera tylko zaślepkę HTML, a nie rzeczywiste bajty pliku. Uprawnienia Graph API są wymagane, aby pobierać załączniki kanału.
- W przypadku jawnych wysyłek z plikiem jako główną zawartością użyj
action=upload-filezmedia/filePath/path; opcjonalnemessagestaje się towarzyszącym tekstem/komentarzem, afilenamenadpisuje przesłaną nazwę.
Bez uprawnień Graph wiadomości kanału z obrazami będą odbierane tylko jako tekst (zawartość obrazu nie jest dostępna dla bota).
Domyślnie OpenClaw pobiera multimedia tylko z nazw hostów Microsoft/Teams. Nadpisz to przez channels.msteams.mediaAllowHosts (użyj ["*"], aby zezwolić na dowolny host).
Nagłówki Authorization są dołączane tylko dla hostów w channels.msteams.mediaAuthAllowHosts (domyślnie hosty Graph + Bot Framework). Utrzymuj tę listę restrykcyjną (unikaj sufiksów wielodzierżawowych).
Wysyłanie plików w czatach grupowych
Boty mogą wysyłać pliki w DM-ach za pomocą przepływu FileConsentCard (wbudowanego). Jednak wysyłanie plików w czatach grupowych/kanałach wymaga dodatkowej konfiguracji:
| Kontekst | Jak wysyłane są pliki | Wymagana konfiguracja |
|---|---|---|
| DM-y | FileConsentCard → użytkownik akceptuje → bot przesyła | Działa od razu |
| Czaty grupowe/kanały | Przesłanie do SharePoint → udostępnienie linku | Wymaga sharePointSiteId + uprawnień Graph |
| Obrazy (dowolny kontekst) | Inline zakodowane w Base64 | Działa od razu |
Dlaczego czaty grupowe wymagają SharePoint
Boty nie mają osobistego dysku OneDrive (punkt końcowy Graph API /me/drive nie działa dla tożsamości aplikacji). Aby wysyłać pliki w czatach grupowych/kanałach, bot przesyła je do witryny SharePoint i tworzy link udostępniania.
Konfiguracja
-
Dodaj uprawnienia Graph API w Entra ID (Azure AD) → App Registration:
Sites.ReadWrite.All(Application) - przesyłanie plików do SharePointChat.Read.All(Application) - opcjonalne, włącza linki udostępniania dla użytkowników
-
Udziel zgody administratora dla dzierżawy.
-
Uzyskaj identyfikator witryny SharePoint:
# 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" -
Skonfiguruj OpenClaw:
{ channels: { msteams: { // ... other config ... sharePointSiteId: "contoso.sharepoint.com,guid1,guid2", }, }, }
Zachowanie udostępniania
| Uprawnienie | Zachowanie udostępniania |
|---|---|
Tylko Sites.ReadWrite.All |
Link udostępniania dla całej organizacji (każdy w organizacji ma dostęp) |
Sites.ReadWrite.All + Chat.Read.All |
Link udostępniania dla użytkowników (dostęp mają tylko członkowie czatu) |
Udostępnianie dla użytkowników jest bezpieczniejsze, ponieważ tylko uczestnicy czatu mogą uzyskać dostęp do pliku. Jeśli brakuje uprawnienia Chat.Read.All, bot wraca do udostępniania w całej organizacji.
Zachowanie awaryjne
| Scenariusz | Wynik |
|---|---|
Czat grupowy + plik + skonfigurowane sharePointSiteId |
Przesłanie do SharePoint, wysłanie linku udostępniania |
Czat grupowy + plik + brak sharePointSiteId |
Próba przesłania do OneDrive (może się nie powieść), wysłanie tylko tekstu |
| Czat osobisty + plik | Przepływ FileConsentCard (działa bez SharePoint) |
| Dowolny kontekst + obraz | Inline zakodowane w Base64 (działa bez SharePoint) |
Lokalizacja przechowywanych plików
Przesłane pliki są przechowywane w folderze /OpenClawShared/ w domyślnej bibliotece dokumentów skonfigurowanej witryny SharePoint.
Ankiety (Adaptive Cards)
OpenClaw wysyła ankiety Teams jako Adaptive Cards (nie ma natywnego API ankiet Teams).
- CLI:
openclaw message poll --channel msteams --target conversation:<id> ... - Głosy są zapisywane przez gateway w
~/.openclaw/msteams-polls.json. - Gateway musi pozostać online, aby zapisywać głosy.
- Ankiety nie publikują jeszcze automatycznie podsumowań wyników (w razie potrzeby sprawdź plik magazynu).
Karty prezentacji
Wysyłaj semantyczne ładunki prezentacji do użytkowników lub konwersacji Teams za pomocą narzędzia message albo CLI. OpenClaw renderuje je jako Teams Adaptive Cards z ogólnego kontraktu prezentacji.
Parametr presentation akceptuje bloki semantyczne. Gdy podano presentation, tekst wiadomości jest opcjonalny.
Narzędzie agenta:
{
action: "send",
channel: "msteams",
target: "user:<id>",
presentation: {
title: "Hello",
blocks: [{ type: "text", text: "Hello!" }],
},
}
CLI:
openclaw message send --channel msteams \
--target "conversation:19:[email protected]" \
--presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello!"}]}'
Szczegóły formatu celu znajdziesz poniżej w sekcji Formaty celów.
Formaty celów
Cele MSTeams używają prefiksów do odróżniania użytkowników od konwersacji:
| Typ celu | Format | Przykład |
|---|---|---|
| Użytkownik (według ID) | user:<aad-object-id> |
user:40a1a0ed-4ff2-4164-a219-55518990c197 |
| Użytkownik (według nazwy) | user:<display-name> |
user:John Smith (wymaga Graph API) |
| Grupa/kanał | conversation:<conversation-id> |
conversation:19:[email protected] |
| Grupa/kanał (surowy) | <conversation-id> |
19:[email protected] (jeśli zawiera @thread) |
Przykłady CLI:
# Send to a user by ID
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"
# Send to a user by display name (triggers Graph API lookup)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"
# Send to a group chat or channel
openclaw message send --channel msteams --target "conversation:19:[email protected]" --message "Hello"
# Send a presentation card to a conversation
openclaw message send --channel msteams --target "conversation:19:[email protected]" \
--presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello"}]}'
Przykłady narzędzi agenta:
{
action: "send",
channel: "msteams",
target: "user:John Smith",
message: "Hello!",
}
{
action: "send",
channel: "msteams",
target: "conversation:19:[email protected]",
presentation: {
title: "Hello",
blocks: [{ type: "text", text: "Hello" }],
},
}
Wiadomości proaktywne
- Wiadomości proaktywne są możliwe tylko po tym, jak użytkownik wszedł w interakcję, ponieważ wtedy przechowujemy odwołania do konwersacji.
- Zobacz
/gateway/configuration, aby uzyskać informacje odmPolicyi bramkowaniu listą dozwolonych.
Identyfikatory zespołu i kanału (częsta pułapka)
Parametr zapytania groupId w adresach URL Teams NIE jest identyfikatorem zespołu używanym do konfiguracji. Zamiast tego wyodrębnij identyfikatory ze ścieżki adresu URL:
Adres URL zespołu:
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
└────────────────────────────┘
Team conversation ID (URL-decode this)
Adres URL kanału:
https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
└─────────────────────────┘
Channel ID (URL-decode this)
Do konfiguracji:
- Klucz zespołu = segment ścieżki po
/team/(po dekodowaniu URL, np.19:[email protected]; starsze dzierżawy mogą pokazywać@thread.skype, co również jest prawidłowe) - Klucz kanału = segment ścieżki po
/channel/(po dekodowaniu URL) - Zignoruj parametr zapytania
groupIddla routingu OpenClaw. To identyfikator grupy Microsoft Entra, a nie identyfikator konwersacji Bot Framework używany w przychodzących aktywnościach Teams.
Kanały prywatne
Boty mają ograniczoną obsługę w kanałach prywatnych:
| Funkcja | Kanały standardowe | Kanały prywatne |
|---|---|---|
| Instalacja bota | Tak | Ograniczona |
| Komunikaty w czasie rzeczywistym (Webhook) | Tak | Może nie działać |
| Uprawnienia RSC | Tak | Mogą działać inaczej |
| @wzmianki | Tak | Jeśli bot jest dostępny |
| Historia Graph API | Tak | Tak (z uprawnieniami) |
Obejścia, jeśli kanały prywatne nie działają:
- Używaj kanałów standardowych do interakcji z botem
- Używaj wiadomości prywatnych - użytkownicy zawsze mogą pisać bezpośrednio do bota
- Używaj Graph API do dostępu historycznego (wymaga
ChannelMessage.Read.All)
Rozwiązywanie problemów
Typowe problemy
- Obrazy nie wyświetlają się w kanałach: Brak uprawnień Graph lub zgody administratora. Zainstaluj ponownie aplikację Teams i całkowicie zamknij oraz ponownie otwórz Teams.
- Brak odpowiedzi w kanale: wzmianki są domyślnie wymagane; ustaw
channels.msteams.requireMention=falsealbo skonfiguruj ustawienia dla zespołu/kanału. - Niezgodność wersji (Teams nadal pokazuje stary manifest): usuń i ponownie dodaj aplikację oraz całkowicie zamknij Teams, aby odświeżyć.
- 401 Unauthorized z Webhook: Oczekiwane przy ręcznym testowaniu bez Azure JWT - oznacza, że punkt końcowy jest osiągalny, ale uwierzytelnianie się nie powiodło. Użyj Azure Web Chat, aby przetestować poprawnie.
Błędy przesyłania manifestu
- "Icon file cannot be empty": Manifest odwołuje się do plików ikon, które mają 0 bajtów. Utwórz prawidłowe ikony PNG (32x32 dla
outline.png, 192x192 dlacolor.png). - "webApplicationInfo.Id already in use": Aplikacja jest nadal zainstalowana w innym zespole/czacie. Najpierw ją znajdź i odinstaluj albo poczekaj 5-10 minut na propagację.
- "Something went wrong" podczas przesyłania: Zamiast tego prześlij przez https://admin.teams.microsoft.com, otwórz narzędzia deweloperskie przeglądarki (F12) → kartę Network i sprawdź treść odpowiedzi, aby zobaczyć rzeczywisty błąd.
- Sideload nie działa: Spróbuj opcji "Upload an app to your org's app catalog" zamiast "Upload a custom app" - często pozwala to ominąć ograniczenia sideload.
Uprawnienia RSC nie działają
- Sprawdź, czy
webApplicationInfo.iddokładnie odpowiada App ID Twojego bota - Prześlij aplikację ponownie i zainstaluj ją ponownie w zespole/czacie
- Sprawdź, czy administrator organizacji nie zablokował uprawnień RSC
- Potwierdź, że używasz właściwego zakresu:
ChannelMessage.Read.Groupdla zespołów,ChatMessage.Read.Chatdla czatów grupowych
Materiały referencyjne
- Utwórz Azure Bot - przewodnik konfiguracji Azure Bot
- Teams Developer Portal - tworzenie aplikacji Teams i zarządzanie nimi
- Schemat manifestu aplikacji Teams
- Odbieranie wiadomości z kanału za pomocą RSC
- Dokumentacja uprawnień RSC
- Obsługa plików przez bota Teams (kanał/grupa wymaga Graph)
- Wiadomości proaktywne
- @microsoft/teams.cli - Teams CLI do zarządzania botem
Powiązane
- Omówienie kanałów - wszystkie obsługiwane kanały
- Parowanie - uwierzytelnianie przez wiadomości prywatne i przepływ parowania
- Grupy - zachowanie czatu grupowego i bramkowanie wzmianek
- Routing kanałów - routing sesji dla wiadomości
- Bezpieczeństwo - model dostępu i wzmacnianie zabezpieczeń