CortexDB Docs
Docs for CortexDB 0.12.8, the version running on CortexDB Cloud (api.cortexdb.ai).
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-hosted — pip 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 ingested: 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}/project:{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 itself is not version-aware

The key is stable rather than content-versioned. The wire key also hashes the content, so an edited message that the poller returns again lands as a new event.

The connector also sets --source-instance-id automatically to the Azure directory (tenant) id, so two Microsoft 365 tenants synced into one scope keep distinct source identities without any extra flag; an explicit CORTEXDB_SOURCE_INSTANCE_ID still overrides it.

The key on the wire is derived

The key format above is this connector's internal record identity: it decides which source record an event belongs to. The idempotency_key actually sent to CortexDB is a derived cxsrc:<56 hex> value that also hashes the content, labels, observed time and actor, so an unchanged redelivery converges on the same event while any edit lands as a new one, even where the key format itself is not content-versioned. Every event also carries a source descriptor with the record's fingerprint. See Source identity and keys.

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

What the connector does not ingest, whatever the configuration:

CapabilityStatus
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