Microsoft Teams integration for LegionIO. Connects to Microsoft Teams via Graph API and Bot Framework for chat, channel, and bot communication.
gem install lex-microsoft_teamsacquire_token— OAuth2 client credentials token for Graph APIacquire_bot_token— OAuth2 token for Bot Frameworkauthorize_url— Build Authorization Code + PKCE authorize URL for delegated consentexchange_code— Exchange authorization code for delegated access/refresh tokensrefresh_delegated_token— Refresh a delegated token using a refresh tokenrequest_device_code— Start Device Code flow (headless fallback)poll_device_code— Poll for Device Code completion (RFC 8628 compliant)
list_joined_teams— List teams the user has joinedget_team— Get team detailslist_team_members— List members of a team
list_chats— List 1:1 and group chatsget_chat— Get chat detailscreate_chat— Create a new chatlist_chat_members— List chat participantsadd_chat_member— Add a member to a chat
list_chat_messages— List messages in a chatget_chat_message— Get a specific messagesend_chat_message— Send a message to a chatreply_to_chat_message— Reply to a messagelist_message_replies— List replies to a message
list_channels— List channels in a teamget_channel— Get channel detailscreate_channel— Create a new channelupdate_channel— Update channel propertiesdelete_channel— Delete a channellist_channel_members— List channel members
list_channel_messages— List messages in a channelget_channel_message— Get a specific channel messagesend_channel_message— Send a message to a channelreply_to_channel_message— Reply to a channel messagelist_channel_message_replies— List replies to a channel message
list_meetings— List online meetings for a userget_meeting— Get meeting detailscreate_meeting— Create an online meetingupdate_meeting— Update meeting propertiesdelete_meeting— Delete a meetingget_meeting_by_join_url— Find a meeting by its join URLlist_attendance_reports— List attendance reports for a meetingget_attendance_report— Get a specific attendance report with attendee records
list_transcripts— List available transcripts for a meetingget_transcript— Get transcript metadataget_transcript_content— Get transcript content (VTT default, DOCX optional viaformat:param)
get_presence— Get the availability and activity status for a user
list_subscriptions— List active subscriptionsget_subscription— Get subscription detailscreate_subscription— Create a change notification subscriptionrenew_subscription— Extend subscription expirationdelete_subscription— Delete a subscriptionsubscribe_to_chat_messages— Subscribe to chat message eventssubscribe_to_channel_messages— Subscribe to channel message events
extract_local_messages— Extract messages from the Teams 2.x LevelDB local storage without Graph API credentialslocal_cache_available?— Check whether the local Teams cache exists on disklocal_cache_stats— Get message count and date range stats from the local cache without extracting
ingest_cache— Ingest messages from the local Teams cache into lex-memory as episodic traces; returns{ stored:, skipped:, latest_time: }
build_card— Build an Adaptive Card payloadtext_block— Create a TextBlock elementfact_set— Create a FactSet elementaction_open_url— Create an OpenUrl actionaction_submit— Create a Submit actionmessage_attachment— Wrap a card as a message attachment
send_activity— Send an activity to a conversationreply_to_activity— Reply to an existing activitysend_text— Send a simple text message via botsend_card— Send an Adaptive Card via botcreate_conversation— Create a new bot conversationget_conversation_members— List conversation members
handle_message— LLM-powered response loop for direct 1:1 bot chats (polls Graph API, replies via Graph or Bot Framework)observe_message— Conversation observer that extracts tasks, context, and relationship data from subscribed human chats (disabled by default, compliance-gated)
Actors:
DirectChatPoller— Polls bot DM chats every 5s, publishes to AMQPObservedChatPoller— Polls subscribed conversations every 30s (disabled by default)MessageProcessor— AMQP subscription actor, routes messages by mode tohandle_messageorobserve_message
Helpers:
SessionManager— Multi-turn LLM session lifecycle with lex-memory persistencePromptResolver— Layered system prompt resolution (settings default -> mode -> per-conversation)HighWaterMark— Per-chat message deduplication via legion-cacheTokenCache— In-memory OAuth token cache with pre-expiry refresh (app + delegated slots)SubscriptionRegistry— Conversation observation subscriptions (in-memory + lex-memory)BrowserAuth— Delegated OAuth orchestrator (PKCE, headless detection, browser launch)CallbackServer— Ephemeral TCP server for OAuth redirect callback
Opt-in browser-based OAuth for delegated Microsoft Graph permissions (e.g., meeting transcripts).
Authorization Code + PKCE (primary): Opens the user's browser for Entra ID login, captures the callback on an ephemeral local port, exchanges the code with PKCE verification.
Device Code (fallback): Automatically selected in headless/SSH environments (no DISPLAY/WAYLAND_DISPLAY). Displays a URL and code for the user to enter on any device.
# Via CLI
# legion auth teams --tenant-id TENANT --client-id CLIENT
# Via code
auth = Legion::Extensions::MicrosoftTeams::Helpers::BrowserAuth.new(
tenant_id: 'your-tenant-id',
client_id: 'your-client-id'
)
result = auth.authenticate # returns token hash with access_token, refresh_token, expires_inTokens are stored in Vault (legionio/microsoft_teams/delegated_token) and silently refreshed before expiry.
The Client class includes all runner modules (Auth, Teams, Chats, Messages, Channels, ChannelMessages, Subscriptions, AdaptiveCards, Bot, Presence, Meetings, Transcripts, LocalCache, CacheIngest).
client = Legion::Extensions::MicrosoftTeams::Client.new(
tenant_id: 'your-tenant-id',
client_id: 'your-app-id',
client_secret: 'your-client-secret'
)
client.authenticate!
# Graph API
client.list_chats
client.send_chat_message(chat_id: 'chat-id', content: 'Hello!')
# Bot Framework
client.send_text(
service_url: 'https://smba.trafficmanager.net/teams/',
conversation_id: 'conv-id',
text: 'Hello from bot'
)
# Local cache (no credentials needed)
client.local_cache_available?
client.extract_local_messages(since: Time.now - 86_400)- Ruby >= 3.4
- LegionIO framework
- Microsoft Entra ID application with appropriate Graph API permissions
MIT