Настройка Microsoft Teams

Подключите Hermes Agent к Microsoft Teams как бота. В отличие от Socket Mode Slack, Teams доставляет сообщения, вызывая публичный HTTPS-вебхук, поэтому вашему экземпляру нужен общедоступный конечный пункт — либо туннель разработки (локальная разработка), либо реальный домен (продакшн).

Нужны сводки встреч из событий Microsoft Graph, а не обычные разговоры с ботом? Используйте специальную страницу настройки: Встречи Teams.

Как бот отвечает

Контекст Поведение
Личный чат (DM) Бот отвечает на каждое сообщение. @упоминание не требуется.
Групповой чат Бот отвечает только при @упоминании.
Канал Бот отвечает только при @упоминании.

Teams доставляет @упоминания как обычные сообщения с тегами <at>BotName</at>, которые Hermes автоматически удаляет перед обработкой.


Шаг 1: Установка Teams CLI

@microsoft/teams.cli автоматизирует регистрацию бота — портал Azure не нужен.

npm install -g @microsoft/teams.cli@preview
teams login

Чтобы проверить вход и найти свой собственный объектный ID AAD (необходим для TEAMS_ALLOWED_USERS):

teams status --verbose

Шаг 2: Открытие порта вебхука

Teams не может доставлять сообщения на localhost. Для локальной разработки используйте любой туннельный инструмент, чтобы получить публичный HTTPS-URL. Порт по умолчанию — 3978 — измените его с помощью TEAMS_PORT, если необходимо.

# devtunnel (Microsoft)
devtunnel create hermes-bot --allow-anonymous
devtunnel port create hermes-bot -p 3978 --protocol https  # replace 3978 with TEAMS_PORT if changed
devtunnel host hermes-bot

# ngrok
ngrok http 3978  # replace 3978 with TEAMS_PORT if changed

# cloudflared
cloudflared tunnel --url http://localhost:3978  # replace 3978 with TEAMS_PORT if changed

Скопируйте https:// URL из вывода — вы используете его на следующем шаге. Оставьте туннель запущенным во время разработки.

Для продакшна укажите конечную точку бота на публичный домен вашего сервера (см. Продакшн-развёртывание).


Шаг 3: Создание бота

teams app create \
  --name "Hermes" \
  --endpoint "https://<your-tunnel-url>/api/messages"

CLI выводит ваш CLIENT_ID, CLIENT_SECRET и TENANT_ID, плюс ссылку для установки на Шаге 6. Сохраните клиентский секрет — он больше не будет показан.


Шаг 4: Настройка переменных окружения

Добавьте в ~/.hermes/.env:

# Required
TEAMS_CLIENT_ID=<your-client-id>
TEAMS_CLIENT_SECRET=<your-client-secret>
TEAMS_TENANT_ID=<your-tenant-id>

# Restrict access to specific users (recommended)
# Use AAD object IDs from `teams status --verbose`
TEAMS_ALLOWED_USERS=<your-aad-object-id>

Шаг 5: Запуск шлюза

HERMES_UID=$(id -u) HERMES_GID=$(id -g) docker compose up -d gateway

Это запустит шлюз. Порт вебхука по умолчанию — 3978 (переопределите с помощью TEAMS_PORT). Проверьте, что он работает:

curl http://localhost:3978/health   # should return: ok
docker logs -f hermes

Look for:

[teams] Webhook server listening on 0.0.0.0:3978/api/messages

Шаг 6: Установка приложения в Teams

teams app get <teamsAppId> --install-link

Откройте напечатанную ссылку в браузере — она откроется прямо в клиенте Teams. После установки отправьте прямое сообщение вашему боту — он готов.


Справочник по конфигурации

Переменные окружения

Переменная Описание
TEAMS_CLIENT_ID Azure AD ID приложения (клиента)
TEAMS_CLIENT_SECRET Azure AD клиентский секрет
TEAMS_TENANT_ID Azure ID тенанта
TEAMS_ALLOWED_USERS Разделённые запятыми объектные ID AAD, которым разрешено использовать бота
TEAMS_ALLOW_ALL_USERS Установите true, чтобы пропустить белый список и разрешить всем
TEAMS_HOME_CHANNEL ID разговора для доставки cron/проактивных сообщений
TEAMS_HOME_CHANNEL_NAME Отображаемое имя для домашнего канала
TEAMS_PORT Порт вебхука (по умолчанию: 3978)

config.yaml

Альтернативно, настройте через ~/.hermes/config.yaml:

platforms:
  teams:
    enabled: true
    extra:
      client_id: "your-client-id"
      client_secret: "your-secret"
      tenant_id: "your-tenant-id"
      port: 3978

Возможности

Интерактивные карточки подтверждения

Когда агенту нужно выполнить потенциально опасную команду, он отправляет Adaptive Card с четырьмя кнопками вместо того, чтобы просить вас ввести /approve:

Нажатие кнопки решает подтверждение инлайн и заменяет карточку решением.

Доставка сводок встреч (Конференц-пайплайн Teams)

When the Teams meeting pipeline plugin is enabled, this adapter also handles outbound delivery of meeting summaries — one Teams integration surface, not two. After a meeting's transcript is summarized, the writer posts the summary into your chosen Teams target.

Pipeline summary delivery is configured under the teams platform entry alongside the bot config:

platforms:
  teams:
    enabled: true
    extra:
      # existing bot config (client_id, client_secret, tenant_id, port) ...

      # Meeting summary delivery (only used when the teams_pipeline plugin is enabled)
      delivery_mode: "graph"       # or "incoming_webhook"
      # For delivery_mode: graph — pick ONE of:
      chat_id: "19:meeting_..."    # post into a Teams chat
      # team_id: "..."             # OR post into a channel
      # channel_id: "..."
      # access_token: "..."        # optional; falls back to MSGRAPH_* app credentials
      # For delivery_mode: incoming_webhook:
      # incoming_webhook_url: "https://outlook.office.com/webhook/..."
Режим Когда использовать Компромисс
incoming_webhook Простая "публикация сводки в этот канал" со статическим URL, сгенерированным Teams. No reply threading, no reactions, shows as the webhook's configured identity.
graph Публикации в каналах с ветвлением или сообщения в чатах 1:1/групповых чатах от имени бота через Microsoft Graph. Requires the Graph app registration with ChannelMessage.Send (channel) or Chat.ReadWrite.All (chat) application permissions.

Если плагин teams_pipeline не включён, эти настройки неактивны — они подключаются только когда рантайм конвейера привязывается к вебхуку Graph.


Продакшн-развёртывание

Для постоянного сервера пропустите devtunnel и зарегистрируйте бота с публичной HTTPS-конечной точкой вашего сервера:

teams app create \
  --name "Hermes" \
  --endpoint "https://your-domain.com/api/messages"

Если вы уже создали бота и просто нужно обновить конечную точку:

teams app update --id <teamsAppId> --endpoint "https://your-domain.com/api/messages"

Убедитесь, что ваш настроенный порт (TEAMS_PORT, по умолчанию 3978) доступен из интернета и что ваш TLS-сертификат действителен — Teams отклоняет самоподписанные сертификаты.


Диагностика

Проблема Решение
health endpoint works but bot doesn't respond Check that your tunnel is still running and the bot's messaging endpoint matches the tunnel URL
KeyError: 'teams' in logs Restart the container — this is fixed in the current version
Bot responds with auth errors Verify TEAMS_CLIENT_ID, TEAMS_CLIENT_SECRET, and TEAMS_TENANT_ID are all set correctly
No inference provider configured Check that ANTHROPIC_API_KEY (or another provider key) is set in ~/.hermes/.env
Bot receives messages but ignores them Your AAD object ID may not be in TEAMS_ALLOWED_USERS. Run teams status --verbose to find it
Tunnel URL changes on restart devtunnel URLs are persistent if you use a named tunnel (devtunnel create hermes-bot). ngrok and cloudflared generate a new URL each run unless you have a paid plan — update the bot endpoint with teams app update when it changes
Teams shows "This bot is not responding" The webhook returned an error. Check docker logs hermes for tracebacks
[teams] Failed to connect in logs The SDK failed to authenticate. Double-check your credentials and that the tenant ID matches the account you used in teams login

Безопасность

**Всегда устанавливайте `TEAMS_ALLOWED_USERS`** с объектными ID AAD авторизованных пользователей. Без этого любой, кто может найти или установить вашего бота, сможет взаимодействовать с ним. Относитесь к `TEAMS_CLIENT_SECRET` как к паролю — периодически меняйте его через портал Azure или Teams CLI.