CortexDB Docs
Connectors

Microsoft Teams Connector

Ingest Microsoft Teams channel messages, threaded replies, and 1:1/group chats into CortexDB.

Captures Teams channel and chat messages via the Microsoft Graph v1.0 API, polled incrementally on lastModifiedDateTime.

Two ways to run this connector

Self-hostedpip install 'cortexdb-connectors[teams]' then cortexdb-sync sync teams. Managed — CortexDB runs the connector as a worker. See the Connectors overview.

Polling only — several capabilities are not ingested

Meeting transcripts, file/attachment contents, Graph change notifications (webhooks), and delta queries are not implemented as of 0.2.20. Messages are collected by polling only. See What is not ingested — it also determines which Graph permissions you need.

1. Prepare credentials in Microsoft Entra (Azure AD)

Azure portal → App registrations → New registration. Add Microsoft Graph application permissions:

PermissionWhy
ChannelMessage.Read.AllRead channel messages and threaded replies
Chat.Read.AllRead 1:1 and group chat messages (only if TEAMS_INCLUDE_CHATS=1)
User.Read.AllResolve message authors to names/emails
TeamMember.Read.AllResolve channel membership for visibility mapping

Have an admin grant tenant-wide consent, then create a client secret and copy it.

Grant only these four permissions

Earlier revisions listed OnlineMeetingTranscript.Read.All — the connector never calls the transcript API, so that consent is not required and should not be requested.

2. Configure (managed dashboard)

Settings → Connectors → Add Connector → Microsoft Teams. Paste the tenant ID, client ID, and client secret; pick the teams to sync; set the scope template (default org:<org>/source:teams/team:{team_id}/channel:{channel_id}); Start sync.

What gets written

Every episode's content is the message body, with HTML stripped to plain text.

EventEpisode typeNotes
Channel messagemessageAuthor resolved to display name + userPrincipalName
Reply in threadmessageparent_id and thread_id link it to the parent message
1:1 / group chat messagemessageOnly when TEAMS_INCLUDE_CHATS=1
Message in a meeting chatmeetingThe chat message, not a transcript
Message with an attachmentdocumentTagged file_share with metadata.attachment_count; the file is not fetched

@-mentions are recorded in metadata.mentions; high-importance messages are tagged high_importance. The idempotency_key is the stable external id:

teams:channel:<team_id>:<channel_id>:<message_id>
teams:chat:<chat_id>:<message_id>

The key is not version-aware

Because the key is stable rather than content-versioned, an edited message dedupes against its first ingest instead of being retained as a new version.

Visibility

SourceVisibility
Standard (public) channelorganization
Private channelrestricted
1:1 / group chatprivate, with the chat's member ids as the allow-list

What is not ingested

Genuine gaps in the shipped package, not configuration you're missing:

CapabilityStatus in 0.2.20
Meeting transcriptsNot implemented (meeting-chat messages are captured; the transcript is not)
File / attachment contentsNot implemented (typed document and counted, but no bytes uploaded)
Graph change notifications (webhooks)Not implemented (no Teams webhook receiver)
Delta queriesNot implemented (uses the lastModifiedDateTime filter with @odata.nextLink paging)

For attachment contents today, the Jira, Slack, and Freshdesk connectors ingest attachments through the blob pipeline.

Run it yourself

pip install 'cortexdb-connectors[teams]'
pip install cortexdb-cli && cortexdb init

export TEAMS_TENANT_ID=...                # required
export TEAMS_CLIENT_ID=...                # required
export TEAMS_CLIENT_SECRET=...            # required
export TEAMS_TEAM_IDS=team-a,team-b       # required for channel ingestion
export TEAMS_INCLUDE_CHATS=0              # 1 to also sync 1:1 / group chats

cortexdb-sync --api-url http://localhost:3141 sync teams
cortexdb-sync --api-url http://localhost:3141 watch teams --interval 60

The connector honours Retry-After on Graph 429s (up to 5 retries), refreshes its token on a mid-sync 401, and paces requests at 1 req/sec. The first run backfills backfill_days (default 30).

See also

On this page