Microsoft Teams (плагин)¶
«Оставь надежду всяк сюда входящий».
Обновлено: 2026-01-21
Статус: поддерживаются текст и вложения в личных сообщениях; отправка файлов в каналы/группы требует sharePointSiteId + разрешений Graph (см. Отправка файлов в групповых чатах). Опросы отправляются через Adaptive Cards.
Требуется плагин¶
Microsoft Teams поставляется как плагин и не входит в базовую установку.
Критическое изменение (2026.1.15): MS Teams вынесен из ядра. Если вы его используете, необходимо установить плагин.
Объяснимо: это делает базовые установки легче и позволяет зависимостям MS Teams обновляться независимо.
Установка через CLI (реестр npm):
openclaw plugins install @openclaw/msteams
Локальная установка (при запуске из git-репозитория):
openclaw plugins install ./extensions/msteams
Если при конфигурации/онбординге выбран Teams и обнаружен git-чекаут, OpenClaw автоматически предложит путь локальной установки.
Подробности: Plugins
Быстрая настройка (для начинающих)¶
- Установите плагин Microsoft Teams.
- Создайте Azure Bot (App ID + client secret + tenant ID).
- Настройте OpenClaw с этими учетными данными.
- Опубликуйте
/api/messages(по умолчанию порт 3978) через публичный URL или туннель. - Установите пакет приложения Teams и запустите Gateway (шлюз).
Минимальный конфиг:
{
channels: {
msteams: {
enabled: true,
appId: "<APP_ID>",
appPassword: "<APP_PASSWORD>",
tenantId: "<TENANT_ID>",
webhook: { port: 3978, path: "/api/messages" },
},
},
}
Примечание: групповые чаты по умолчанию заблокированы (channels.msteams.groupPolicy: "allowlist"). Чтобы разрешить ответы в группах, установите channels.msteams.groupAllowFrom (или используйте groupPolicy: "open", чтобы разрешить любого участника, с обязательным упоминанием).
Цели¶
- Общение с OpenClaw через личные сообщения Teams, групповые чаты или каналы.
- Детерминированная маршрутизация: ответы всегда возвращаются в тот же канал, откуда пришли.
- Безопасное поведение каналов по умолчанию (требуются упоминания, если не настроено иначе).
Запись конфига¶
По умолчанию Microsoft Teams разрешено записывать обновления конфига, инициированные /config set|unset (требуется commands.config: true).
Отключить:
{
channels: { msteams: { configWrites: false } },
}
Контроль доступа (личные сообщения + группы)¶
Доступ к личным сообщениям
- По умолчанию:
channels.msteams.dmPolicy = "pairing". Неизвестные отправители игнорируются до одобрения. channels.msteams.allowFromпринимает AAD object ID, UPN или отображаемые имена. Мастер настраивания разрешает имена в ID через Microsoft Graph при наличии учетных данных.
Доступ к группам
- По умолчанию:
channels.msteams.groupPolicy = "allowlist"(заблокировано, пока вы не добавитеgroupAllowFrom). Используйтеchannels.defaults.groupPolicyдля переопределения значения по умолчанию, если оно не задано. channels.msteams.groupAllowFromуправляет тем, какие отправители могут инициировать события в групповых чатах/каналах (с откатом кchannels.msteams.allowFrom).- Установите
groupPolicy: "open", чтобы разрешить любого участника (по умолчанию все равно требуется упоминание). - Чтобы запретить все каналы, установите
channels.msteams.groupPolicy: "disabled".
Пример:
{
channels: {
msteams: {
groupPolicy: "allowlist",
groupAllowFrom: ["user@org.com"],
},
},
}
Списки разрешённых Teams + каналов
- Ограничивайте ответы в группах/каналах, перечисляя команды и каналы в
channels.msteams.teams. - Ключами могут быть ID или имена команд; ключами каналов — ID диалогов или имена.
- Когда включен
groupPolicy="allowlist"и присутствует allowlist команд, принимаются только перечисленные команды/каналы (с обязательным упоминанием). - Мастер конфигурации принимает записи
Team/Channelи сохраняет их за вас. - При запуске OpenClaw разрешает имена команд/каналов и пользователей из allowlist в ID (если позволяют разрешения Graph) и логирует сопоставление; неразрешённые записи сохраняются как введены.
Пример:
{
channels: {
msteams: {
groupPolicy: "allowlist",
teams: {
"My Team": {
channels: {
General: { requireMention: true },
},
},
},
},
},
}
Как это работает¶
- Установите плагин Microsoft Teams.
- Создайте Azure Bot (App ID + secret + tenant ID).
- Соберите пакет приложения Teams, который ссылается на бота и включает разрешения RSC ниже.
- Загрузите/установите приложение Teams в команду (или в личную область для личных сообщений).
- Настройте
msteamsв~/.openclaw/openclaw.json(или через переменные окружения) и запустите Gateway (шлюз). - Gateway (шлюз) по умолчанию принимает трафик вебхуков Bot Framework на
/api/messages.
Настройка Azure Bot (Предварительные требования)¶
Перед конфигурацией OpenClaw необходимо создать ресурс Azure Bot.
Шаг 1: Создание Azure Bot¶
- Перейдите на Create Azure Bot
- Заполните вкладку Basics:
| Поле | Значение |
|---|---|
| Имя бота | Имя вашего бота, например openclaw-msteams (должно быть уникальным) |
| Подписка | Выберите подписку Azure |
| Группа ресурсов | Создайте новую или используйте существующую |
| Ценовой уровень | Free для разработки/тестирования |
| Тип приложения | Single Tenant (рекомендуется — см. примечание ниже) |
| Тип создания | Create new Microsoft App ID |
Уведомление об устаревании: Создание новых мультиарендных ботов было прекращено после 2025-07-31. Для новых ботов используйте Single Tenant.
- Нажмите Review + create → Create (подождите ~1–2 минуты)
Шаг 2: Получение учетных данных¶
- Перейдите в ресурс Azure Bot → Configuration
- Скопируйте Microsoft App ID → это ваш
appId - Нажмите Manage Password → перейдите в App Registration
- В Certificates & secrets → New client secret → скопируйте Value → это ваш
appPassword - Перейдите в Overview → скопируйте Directory (tenant) ID → это ваш
tenantId
Шаг 3: Настройка конечной точки сообщений¶
- В Azure Bot → Configuration
- Установите Messaging endpoint на URL вашего вебхука:
- Продакшн:
https://your-domain.com/api/messages- Локальная разработка: используйте туннель (см. Локальная разработка ниже)
Шаг 4: Включение канала Teams¶
- В Azure Bot → Channels
- Нажмите Microsoft Teams → Configure → Save
- Примите Условия использования
Локальная разработка (туннелирование)¶
Teams не может обратиться к localhost. Для локальной разработки используйте туннель:
Вариант A: ngrok
ngrok http 3978
# Copy the https URL, e.g., https://abc123.ngrok.io
# Set messaging endpoint to: https://abc123.ngrok.io/api/messages
Вариант B: Tailscale Funnel
tailscale funnel 3978
# Use your Tailscale funnel URL as the messaging endpoint
Teams Developer Portal (альтернатива)¶
Вместо ручного создания ZIP-манифеста вы можете использовать Teams Developer Portal:
- Нажмите + New app
- Заполните базовую информацию (имя, описание, данные разработчика)
- Перейдите в App features → Bot
- Выберите Enter a bot ID manually и вставьте App ID вашего Azure Bot
- Отметьте области: Personal, Team, Group Chat
- Нажмите Distribute → Download app package
- В Teams: Apps → Manage your apps → Upload a custom app → выберите ZIP
Часто это проще, чем редактировать JSON-манифесты вручную.
Тестирование бота¶
Вариант A: Azure Web Chat (сначала проверьте вебхук)
- В Azure Portal → ресурс Azure Bot → Test in Web Chat
- Отправьте сообщение — вы должны увидеть ответ
- Это подтверждает, что конечная точка вебхука работает до настройки Teams
Вариант B: Teams (после установки приложения)
- Установите приложение Teams (sideload или каталог организации)
- Найдите бота в Teams и отправьте личное сообщение
- Проверьте логи Gateway (шлюза) на входящую активность
Настройка (минимальная, только текст)¶
-
Установка плагина Microsoft Teams - Из npm:
openclaw plugins install @openclaw/msteams- Из локального чекаута:openclaw plugins install ./extensions/msteams -
Регистрация бота - Создайте Azure Bot (см. выше) и запишите:
- App ID
- Client secret (пароль приложения)
- Tenant ID (single-tenant)
-
Манифест приложения Teams - Добавьте запись
botсbotId = <App ID>. - Области:personal,team,groupChat. -supportsFiles: true(обязательно для обработки файлов в личной области). - Добавьте разрешения RSC (ниже). - Создайте иконки:outline.png(32x32) иcolor.png(192x192). - Упакуйте все три файла в ZIP:manifest.json,outline.png,color.png. -
Настройка OpenClaw
json
{
"msteams": {
"enabled": true,
"appId": "<APP_ID>",
"appPassword": "<APP_PASSWORD>",
"tenantId": "<TENANT_ID>",
"webhook": { "port": 3978, "path": "/api/messages" }
}
}
Вы также можете использовать переменные окружения вместо ключей конфига:
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
-
Конечная точка бота - Установите Messaging Endpoint Azure Bot в:
https://<host>:3978/api/messages(или выбранный вами путь/порт).
-
Запуск Gateway (шлюза) - Канал Teams запускается автоматически, когда плагин установлен и существует конфиг
msteamsс учетными данными.
Контекст истории¶
channels.msteams.historyLimitуправляет тем, сколько последних сообщений канала/группы включается в prompt.- С откатом к
messages.groupChat.historyLimit. Установите0, чтобы отключить (по умолчанию 50). - История личных сообщений может быть ограничена с помощью
channels.msteams.dmHistoryLimit(повороты пользователя). Переопределения для конкретных пользователей:channels.msteams.dms["<user_id>"].historyLimit.
Текущие разрешения Teams RSC (манифест)¶
Это существующие resourceSpecific разрешения в нашем манифесте приложения Teams. Они применяются только внутри команды/чата, где установлено приложение.
Для каналов (область команды):
ChannelMessage.Read.Group(Application) — получение всех сообщений канала без @упоминанияChannelMessage.Send.Group(Application)Member.Read.Group(Application)Owner.Read.Group(Application)ChannelSettings.Read.Group(Application)TeamMember.Read.Group(Application)TeamSettings.Read.Group(Application)
Для групповых чатов:
ChatMessage.Read.Chat(Application) — получение всех сообщений группового чата без @упоминания
Пример манифеста Teams (сокращённый)¶
Минимальный, корректный пример с обязательными полями. Замените ID и 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" }
]
}
}
}
Ограничения манифеста (обязательные поля)¶
bots[].botIdдолжен совпадать с Azure Bot App ID.webApplicationInfo.idдолжен совпадать с Azure Bot App ID.bots[].scopesдолжен включать поверхности, которые вы планируете использовать (personal,team,groupChat).bots[].supportsFiles: trueтребуется для обработки файлов в личной области.authorization.permissions.resourceSpecificдолжен включать чтение/отправку каналов, если вы хотите трафик каналов.
Обновление существующего приложения¶
Чтобы обновить уже установленное приложение Teams (например, для добавления разрешений RSC):
- Обновите ваш
manifest.jsonс новыми настройками - Увеличьте поле
version(например,1.0.0→1.1.0) - Переупакуйте ZIP манифеста с иконками (
manifest.json,outline.png,color.png) - Загрузите новый ZIP: - Вариант A (Teams Admin Center): Teams Admin Center → Teams apps → Manage apps → найдите приложение → Upload new version - Вариант B (Sideload): В Teams → Apps → Manage your apps → Upload a custom app
- Для каналов команды: переустановите приложение в каждой команде, чтобы новые разрешения вступили в силу
- Полностью закройте и перезапустите Teams (не просто закройте окно), чтобы очистить кэш метаданных приложения
Возможности: только RSC vs Graph¶
С только Teams RSC (приложение установлено, без разрешений Graph API)¶
Работает:
- Чтение текста сообщений каналов.
- Отправка текста сообщений каналов.
- Получение вложений файлов в личных сообщениях.
Не работает:
- Изображения или файлы в каналах/группах (в полезной нагрузке только HTML-заглушка).
- Загрузка вложений, хранящихся в SharePoint/OneDrive.
- Чтение истории сообщений (кроме события живого вебхука).
С Teams RSC + разрешениями Microsoft Graph (Application)¶
Добавляется:
- Загрузка размещённого контента (изображения, вставленные в сообщения).
- Загрузка файловых вложений из SharePoint/OneDrive.
- Чтение истории сообщений каналов/чатов через Graph.
RSC vs Graph API¶
| Возможность | Разрешения RSC | Graph API |
|---|---|---|
| Сообщения в реальном времени | Да (через вебхук) | Нет (только опрос) |
| Исторические сообщения | Нет | Да (можно запрашивать историю) |
| Сложность настройки | Только манифест приложения | Требуется согласие администратора + поток токенов |
| Работа офлайн | Нет (должен работать) | Да (можно запрашивать в любое время) |
Итог: RSC — для прослушивания в реальном времени; Graph API — для доступа к истории. Чтобы догонять пропущенные сообщения в офлайне, нужен Graph API с ChannelMessage.Read.All (требуется согласие администратора).
Медиа и история с Graph (требуется для каналов)¶
Если вам нужны изображения/файлы в каналах или получение истории сообщений, необходимо включить разрешения Microsoft Graph и выдать согласие администратора.
- В Entra ID (Azure AD) → App Registration добавьте разрешения Microsoft Graph Application:
-
ChannelMessage.Read.All(вложения каналов + история) -Chat.Read.AllилиChatMessage.Read.All(групповые чаты) - Выдайте согласие администратора для арендатора.
- Увеличьте версию манифеста приложения Teams, повторно загрузите и переустановите приложение в Teams.
- Полностью закройте и перезапустите Teams, чтобы очистить кэш метаданных приложения.
Известные ограничения¶
Тайм-ауты вебхука¶
Teams доставляет сообщения через HTTP-вебхук. Если обработка занимает слишком много времени (например, медленные ответы LLM), вы можете увидеть:
- Тайм-ауты Gateway (шлюза)
- Повторные попытки Teams (вызывающие дубликаты)
- Потерянные ответы
OpenClaw решает это, быстро возвращая ответ и отправляя сообщения проактивно, но очень медленные ответы всё ещё могут вызывать проблемы.
Форматирование¶
Markdown в Teams более ограничен, чем в Slack или Discord:
- Базовое форматирование работает: жирный, курсив,
code, ссылки - Сложный markdown (таблицы, вложенные списки) может отображаться некорректно
- Adaptive Cards поддерживаются для опросов и произвольных карточек (см. ниже)
Конфигурация¶
Ключевые настройки (см. /gateway/configuration для общих шаблонов каналов):
channels.msteams.enabled: включить/выключить канал.channels.msteams.appId,channels.msteams.appPassword,channels.msteams.tenantId: учетные данные бота.channels.msteams.webhook.port(по умолчанию3978)channels.msteams.webhook.path(по умолчанию/api/messages)channels.msteams.dmPolicy:pairing | allowlist | open | disabled(по умолчанию: pairing)channels.msteams.allowFrom: список разрешённых для личных сообщений (AAD object ID, UPN или отображаемые имена). Мастер разрешает имена в ID во время настройки при наличии доступа Graph.channels.msteams.textChunkLimit: размер чанка исходящего текста.channels.msteams.chunkMode:length(по умолчанию) илиnewlineдля разделения по пустым строкам (границы абзацев) перед разбиением по длине.channels.msteams.mediaAllowHosts: список разрешённых хостов для входящих вложений (по умолчанию домены Microsoft/Teams).channels.msteams.mediaAuthAllowHosts: список разрешённых хостов для добавления заголовков Authorization при повторах загрузки медиа (по умолчанию хосты Graph + Bot Framework).channels.msteams.requireMention: требовать @упоминание в каналах/группах (по умолчанию true).channels.msteams.replyStyle:thread | top-level(см. Стиль ответа).channels.msteams.teams.<teamId>.replyStyle: переопределение для команды.channels.msteams.teams.<teamId>.requireMention: переопределение для команды.channels.msteams.teams.<teamId>.tools: значения по умолчанию переопределений политик инструментов для команды (allow/deny/alsoAllow), используемые, когда отсутствует переопределение канала.channels.msteams.teams.<teamId>.toolsBySender: значения по умолчанию переопределений политик инструментов для команды и отправителя ("*"поддерживает wildcard).channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: переопределение для канала.channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: переопределение для канала.channels.msteams.teams.<teamId>.channels.<conversationId>.tools: переопределения политик инструментов для канала (allow/deny/alsoAllow).channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: переопределения политик инструментов для канала и отправителя ("*"поддерживает wildcard).channels.msteams.sharePointSiteId: ID сайта SharePoint для загрузки файлов в групповых чатах/каналах (см. Отправка файлов в групповых чатах).
Маршрутизация и сессии¶
- Ключи сессий следуют стандартному формату агента (см. /concepts/session):
- Личные сообщения используют основную сессию (
agent:<agentId>:<mainKey>). - Сообщения каналов/групп используют ID диалога:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
Стиль ответа: Threads vs Posts¶
Недавно Teams представил два UI-стиля каналов поверх одной и той же модели данных:
| Стиль | Описание | Рекомендуемый replyStyle |
|---|---|---|
| Posts (классический) | Сообщения отображаются карточками с ответами в треде | thread (по умолчанию) |
| Threads (как в Slack) | Сообщения идут линейно, как в Slack | top-level |
Проблема: API Teams не сообщает, какой UI-стиль используется в канале. Если выбрать неверный replyStyle:
threadв канале со стилем Threads → ответы выглядят неудачно вложеннымиtop-levelв канале со стилем Posts → ответы появляются как отдельные верхнеуровневые посты, а не в треде
Решение: Настройте replyStyle для каждого канала в зависимости от его настройки:
{
"msteams": {
"replyStyle": "thread",
"teams": {
"19:abc...@thread.tacv2": {
"channels": {
"19:xyz...@thread.tacv2": {
"replyStyle": "top-level"
}
}
}
}
}
}
Вложения и изображения¶
Текущие ограничения:
- Личные сообщения: изображения и файловые вложения работают через API файлов бота Teams.
- Каналы/группы: вложения хранятся в M365 (SharePoint/OneDrive). Полезная нагрузка вебхука содержит только HTML-заглушку, а не байты файла. Для загрузки вложений каналов требуются разрешения Graph API.
Без разрешений Graph сообщения каналов с изображениями будут получены как только текст (содержимое изображения боту недоступно).
По умолчанию OpenClaw загружает медиа только с хостов Microsoft/Teams. Переопределите с помощью channels.msteams.mediaAllowHosts (используйте ["*"], чтобы разрешить любой хост).
Заголовки Authorization добавляются только для хостов из channels.msteams.mediaAuthAllowHosts (по умолчанию хосты Graph + Bot Framework). Держите этот список строгим (избегайте многопользовательских суффиксов).
Отправка файлов в групповых чатах¶
Боты могут отправлять файлы в личных сообщениях, используя поток FileConsentCard (встроенный). Однако отправка файлов в групповых чатах/каналах требует дополнительной настройки:
| Контекст | Как отправляются файлы | Требуемая настройка |
|---|---|---|
| Личные сообщения | FileConsentCard → пользователь принимает → бот загружает | Работает из коробки |
| Групповые чаты/каналы | Загрузка в SharePoint → ссылка для доступа | Требуется sharePointSiteId + разрешения Graph |
| Изображения (любой контекст) | Base64 inline | Работает из коробки |
Почему группам нужен SharePoint¶
У ботов нет личного диска OneDrive (конечная точка Graph API /me/drive не работает для application identity). Чтобы отправлять файлы в групповых чатах/каналах, бот загружает их на сайт SharePoint и создаёт ссылку общего доступа.
Настройка¶
-
Добавьте разрешения Graph API в Entra ID (Azure AD) → App Registration: -
Sites.ReadWrite.All(Application) — загрузка файлов в SharePoint -Chat.Read.All(Application) — необязательно, включает ссылки общего доступа для каждого пользователя -
Выдайте согласие администратора для арендатора.
-
Получите ID сайта SharePoint:
```bash # 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:
json5
{
channels: {
msteams: {
// ... other config ...
sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
},
},
}
Поделиться поведением¶
| Разрешение | Поделиться поведением |
|---|---|
Только Sites.ReadWrite.All |
Ссылка для всей организации (доступна всем в организации) |
Sites.ReadWrite.All + Chat.Read.All |
Ссылка для каждого пользователя (доступ только участникам чата) |
Общий доступ для каждого пользователя более безопасен, так как файл доступен только участникам чата. Если отсутствует разрешение Chat.Read.All, бот использует общий доступ для организации.
Резервное поведение¶
| Сценарий | Результат |
|---|---|
Групповой чат + файл + настроен sharePointSiteId |
Загрузка в SharePoint, отправка ссылки |
Групповой чат + файл + нет sharePointSiteId |
Попытка загрузки в OneDrive (может не сработать), отправка только текста |
| Личный чат + файл | Поток FileConsentCard (работает без SharePoint) |
| Любой контекст + изображение | Base64 inline (работает без SharePoint) |
Место хранения файлов¶
Загруженные файлы хранятся в папке /OpenClawShared/ в стандартной библиотеке документов настроенного сайта SharePoint.
Опросы (Adaptive Cards)¶
OpenClaw отправляет опросы Teams как Adaptive Cards (в Teams нет нативного API опросов).
- CLI:
openclaw message poll --channel msteams --target conversation:<id> ... - Голоса записываются Gateway (шлюзом) в
~/.openclaw/msteams-polls.json. - Gateway (шлюз) должен оставаться онлайн для записи голосов.
- Автоматическая публикация итогов опросов пока не реализована (при необходимости проверяйте файл хранилища).
Adaptive Cards (произвольные)¶
Отправляйте любой JSON Adaptive Card пользователям или в диалоги Teams с помощью инструмента или CLI message.
Параметр card принимает объект JSON Adaptive Card. При указании card текст сообщения необязателен.
Инструмент агента:
{
"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!"}]}'
См. документацию Adaptive Cards для схемы и примеров. Детали целевых форматов см. ниже в разделе Целевые форматы.
Целевые форматы¶
Цели MSTeams используют префиксы для различения пользователей и диалогов:
| Тип цели | Формат | Пример |
|---|---|---|
| Пользователь (по ID) | user:<aad-object-id> |
user:40a1a0ed-4ff2-4164-a219-55518990c197 |
| Пользователь (по имени) | user:<display-name> |
user:John Smith (требуется Graph API) |
| Группа/канал | conversation:<conversation-id> |
conversation:19:abc123...@thread.tacv2 |
| Группа/канал (raw) | <conversation-id> |
19:abc123...@thread.tacv2 (если содержит @thread) |
Примеры 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: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"}]}'
Примеры инструментов агента:
{
"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" }]
}
}
Примечание: без префикса user: имена по умолчанию разрешаются как группы/команды. Всегда используйте user: при обращении к людям по отображаемому имени.
Проактивные сообщения¶
- Проактивные сообщения возможны только после того, как пользователь взаимодействовал, так как мы сохраняем ссылки диалогов в этот момент.
- См.
/gateway/configurationдляdmPolicyи ограничений allowlist.
ID команд и каналов (частая ошибка)¶
Параметр запроса groupId в URL Teams НЕ является ID команды для конфигурации. Извлекайте ID из пути URL:
URL команды:
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
└────────────────────────────┘
Team ID (URL-decode this)
URL канала:
https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
└─────────────────────────┘
Channel ID (URL-decode this)
Для конфига:
- ID команды = сегмент пути после
/team/(URL-decoded, например19:Bk4j...@thread.tacv2) - ID канала = сегмент пути после
/channel/(URL-decoded) - Игнорируйте параметр запроса
groupId
Приватные каналы¶
Поддержка ботов в приватных каналах ограничена:
| Функция | Стандартные каналы | Приватные каналы |
|---|---|---|
| Установка бота | Да | Ограничено |
| Сообщения в реальном времени (вебхук) | Да | Может не работать |
| Разрешения RSC | Да | Могут вести себя иначе |
| @упоминания | Да | Если бот доступен |
| История Graph API | Да | Да (с разрешениями) |
Обходные пути, если приватные каналы не работают:
- Используйте стандартные каналы для взаимодействия с ботом
- Используйте личные сообщения — пользователи всегда могут написать боту напрямую
- Используйте Graph API для доступа к истории (требуется
ChannelMessage.Read.All)
Устранение неполадок¶
Распространённые проблемы¶
- Изображения не отображаются в каналах: отсутствуют разрешения Graph или согласие администратора. Переустановите приложение Teams и полностью закройте/откройте Teams.
- Нет ответов в канале: по умолчанию требуются упоминания; установите
channels.msteams.requireMention=falseили настройте для команды/канала. - Несоответствие версий (Teams показывает старый манифест): удалите и снова добавьте приложение и полностью перезапустите Teams для обновления.
- 401 Unauthorized от вебхука: ожидаемо при ручном тестировании без JWT Azure — означает, что конечная точка доступна, но аутентификация не прошла. Используйте Azure Web Chat для корректного теста.
Ошибки загрузки манифеста¶
- «Icon file cannot be empty»: манифест ссылается на иконки нулевого размера. Создайте корректные PNG-иконки (32x32 для
outline.png, 192x192 дляcolor.png). - «webApplicationInfo.Id already in use»: приложение всё ещё установлено в другой команде/чате. Найдите и удалите его или подождите 5–10 минут для распространения.
- «Something went wrong» при загрузке: загрузите через https://admin.teams.microsoft.com, откройте DevTools браузера (F12) → вкладка Network и проверьте тело ответа с фактической ошибкой.
- Сбой sideload: попробуйте «Upload an app to your org's app catalog» вместо «Upload a custom app» — это часто обходит ограничения sideload.
Разрешения RSC не работают¶
- Проверьте, что
webApplicationInfo.idточно совпадает с App ID вашего бота - Повторно загрузите приложение и переустановите его в команде/чате
- Убедитесь, что администратор организации не заблокировал разрешения RSC
- Подтвердите, что используется правильная область:
ChannelMessage.Read.Groupдля команд,ChatMessage.Read.Chatдля групповых чатов
Ссылки¶
- Create Azure Bot — руководство по настройке Azure Bot
- Teams Developer Portal — создание и управление приложениями Teams
- Teams app manifest schema
- Receive channel messages with RSC
- RSC permissions reference
- Teams bot file handling (для каналов/групп требуется Graph)
- Proactive messaging