Настройка 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 |
Безопасность
-
Store credentials in
~/.hermes/.envwith permissions600(chmod 600 ~/.hermes/.env) -
The bot only accepts messages from users in
TEAMS_ALLOWED_USERS; unauthorized messages are silently dropped -
Your public endpoint (
/api/messages) is authenticated by the Teams Bot Framework — requests without valid JWTs are rejected