Skip to main content

Microsoft Teams Integration

Connect Microsoft Teams to capture decisions from your team's conversations.

Features​

  • Real-time capture - @Align to capture decisions instantly
  • Context extraction - Automatically includes surrounding conversation
  • Channel support - Works in team channels
  • Discover - Scan historical messages for past decisions

Setup (Cloud)​

  1. Go to Settings → Integrations in Align
  2. Click Connect Teams
  3. Sign in with your Microsoft account
  4. Grant permissions for your tenant
  5. Add the Align bot to your desired channels

Adding Align to Channels​

After connecting:

  1. Go to the Teams channel
  2. Click + to add a tab/app
  3. Search for "Align"
  4. Add the Align bot to the channel

Capturing Decisions​

Basic Capture​

Mention @Align with the decision:

@Align We decided to migrate to Azure Kubernetes Service

With Context​

Include rationale for richer snapshots:

@Align Moving to AKS for the platform migration.
Key factors:
- Better integration with existing Azure services
- Cost optimization through reserved instances
- Team already has Azure expertise

Commands​

TriggerDescription
@Align <decision>Capture a new decision
@Align helpShow available commands
React with 📌 or 🔖Capture the message you reacted to
Meeting transcriptA decision-relevant Teams meeting transcript is analysed after the meeting

Ambient suggestions are off by default and enabled per channel. Nothing is stored unless someone confirms. See Capture.

Best Practices​

  1. Use standard channels - Align works best in team channels
  2. Be descriptive - Teams messages are often shorter, add context
  3. Capture in threads - Reply to the discussion with the decision
  4. Include stakeholders - Mention decision makers

Permissions​

Align requests these delegated Microsoft Graph permissions when an account connects. Each one is limited to what the connecting account can already see, so connect a dedicated service account that belongs only to the teams you want captured. Historical scans use only these.

PermissionPurpose
openid, profile, email, User.ReadSign the connecting account in
offline_accessKeep the connection alive after sign-in
Team.ReadBasic.All, Channel.ReadBasic.AllList the teams and channels the account belongs to
ChannelMessage.Read.AllRead channel messages and threads
Chat.ReadRead chats the connecting account is part of
OnlineMeetings.Read, OnlineMeetingTranscript.Read.All, Calendars.ReadFind meetings the account can access and read their transcripts

Real-time meeting transcripts use an application permission. Capturing a transcript as soon as a meeting ends uses the connector's own app identity (a client-credentials token, visible in your Entra sign-in logs) and the application permission OnlineMeetingTranscript.Read.All, which covers the tenant's transcripts unless you restrict it with a Teams application access policy. If you do not grant it, transcripts are still picked up by scheduled scans through the delegated grant above.

New channel messages are captured by re-scanning or when someone mentions @Align; the Teams app does not subscribe to every channel message. Replies to @Align go through the Teams bot, not through the connecting account's token. Corrected 2026-09-24: this table previously listed ChannelMessage.Send and User.Read.All, which Align does not request, and omitted the chat, meeting and transcript permissions it does.

Troubleshooting​

Align doesn't respond​

  • Ensure the Align app is installed in your tenant
  • Verify the bot is added to the channel
  • Check that the bot is not blocked

Permission errors​

  • Your Teams admin may need to approve the app
  • Enterprise tenants may require admin consent

Self-Hosted Setup​

On Align cloud, Align's OAuth app is used. Self-hosted, you register your own Microsoft Entra app. See OAuth apps.

Delegated-only installs​

If your Azure AD admin granted only delegated permissions (no Application permission for meeting transcripts), set connectors.teams.disableRealtimeTranscripts: true. This turns off the tenant-wide real-time transcript subscription, which needs an app-only token the Application permission provides. Discover scans keep working over your delegated scopes. See Values reference.

Registering your own Azure Bot and Teams app package​

If you register your own Microsoft Entra ID app for Teams, you also need your own Teams app package - the zip a user uploads to install the bot. Align's own package is not usable for this: it names Align's own bot and only allows align.tech domains, so a customer's Teams tenant would try to talk to Align's bot, not yours.

Registering your own app for Teams means setting two sets of credentials from the same -oauth-teams secret: TEAMS_CLIENT_ID/TEAMS_CLIENT_SECRET (the OAuth app, used to read channel messages via Microsoft Graph) and TEAMS_BOT_APP_ID/TEAMS_BOT_APP_PASSWORD/TEAMS_BOT_APP_TENANT_ID (the Bot Framework identity, used to receive @Align mentions and slash commands). A single-tenant Entra app registration can serve as both, and its Application (client) ID is what goes in the manifest as the bot id.

  1. Create an Azure Bot resource in the Azure Portal, using the same Entra app registration as your TEAMS_CLIENT_ID. Note its Microsoft App ID (Application client ID) - this is the bot-id below, and also TEAMS_BOT_APP_ID. Generate a client secret for it and set that as TEAMS_BOT_APP_PASSWORD; set the app registration's own tenant as TEAMS_BOT_APP_TENANT_ID (for a single-tenant registration - leaving it unset falls back to MultiTenant). For secrets.create: true, these are secrets.oauth.teams.botAppId, botAppPassword and botAppTenantId; otherwise set the bot-app-id, bot-app-password and tenant-id keys directly on the -oauth-teams Secret you pre-create.

  2. Set the bot's messaging endpoint to https://{your-api-domain}/webhook/teams (the same domain as gateway.apiBaseUrl - the gateway proxies this route to the connector), then add the Microsoft Teams channel to the bot.

  3. Generate a Teams app id. This is a separate GUID you choose to identify the app package - uuidgen on macOS/Linux, or any GUID generator. It does not need to match the bot id, though it may.

  4. Render the package from connectors/mcp-teams/teams-app-manifest/render-package.sh in the align-stack repository:

    ./render-package.sh <bot-id> <teams-app-id> <your-api-domain> [output-dir]

    This fills in manifest.template.json's placeholders (bot id, app id, validDomains) and zips the result with the icons into align-teams-app.zip. It refuses to produce a package with an unfilled placeholder or invalid JSON. Optional environment variables (DEVELOPER_NAME, DEVELOPER_WEBSITE_URL, DEVELOPER_PRIVACY_URL, DEVELOPER_TERMS_URL, PACKAGE_NAME) let you set your own developer identity in the package; each has a placeholder default if unset.

  5. Upload the package. In Teams, go to Apps → Manage your apps → Upload a custom app (or the Teams admin center's equivalent), and select the generated align-teams-app.zip.

A test asserting the rendered package never carries Align's own bot id or align.tech runs in CI (scripts/__tests__/test-teams-manifest-template.sh).