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: }
get_profile— Get Graph API profile for a user (default:/me)list_people— List relevant people for a user via/me/people
list_meeting_ai_insights— List AI-generated insights for an online meetingget_meeting_ai_insight— Get a specific AI insightlist_meeting_recordings— List recordings for an online meetingget_meeting_recording— Get a specific meeting recordinglist_call_records— List call records from Graph APIget_call_record— Get a specific call record
sync_owners— Sync team ownership data from Graph API (single team or all teams)detect_orphans— Detect teams with no current ownersget_team_owners— Get owners for a specific team
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:
CacheBulkIngest— Once at startup: full local LevelDB cache ingestCacheSync— Every 5min: incremental new-message ingest from local cacheDirectChatPoller— Every 5s: polls bot DM chats via Graph API, publishes to AMQPObservedChatPoller— Every 30s: polls subscribed conversations (compliance-gated, disabled by default)MessageProcessor— AMQP subscription actor, routes messages by modeAuthValidator— Once at boot: validates and restores delegated tokensTokenRefresher— Every 15min: keeps delegated tokens freshProfileIngest— Once (5s delay): four-phase cognitive data pipeline after authApiIngest— Every 30min: Graph API ingest with HWM dedupChannelPoller— Every 60s: polls joined team channels for new messagesMeetingIngest— Every 5min: polls online meetings, fetches transcripts and AI insightsPresencePoller— Every 60s: polls Graph API presence, logs changesAbsorbMeeting— Subscription: absorbs Teams meeting data via absorber frameworkIncrementalSync— Every 15min: periodic re-sync with HWM dedup
Helpers:
SessionManager— Multi-turn LLM session lifecycle with lex-memory persistencePromptResolver— Layered system prompt resolution (settings default -> mode -> per-conversation -> trace context)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 callbackTraceRetriever— Retrieves and formats memory traces as LLM context (2000-token budget, strength-ranked dedup)
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 at a per-user path ({USER}/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, People, ProfileIngest, ApiIngest, AiInsights, Ownership).
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