Microsoft Teams Integration
Connect Microsoft Teams to work with Autoheal from your channels — @mention the bot to ask a question or kick off an investigation, and it replies in the thread. Autoheal answers conversationally by default and spins up a full investigation when you ask it to look into something. (Routing alerts to Teams channels arrives in a later release.)
Teams runs on Microsoft Entra ID (Azure AD) and the Bot Framework. Connecting takes a Microsoft Entra tenant with Teams and an admin who can grant tenant consent — it does not work on the free/consumer "Microsoft Teams" tier (there's no admin-consent-capable tenant behind it).
What the agent can do
Once connected, the AI agent can:
| Capability | Description |
|---|---|
| @Mention in channels | Mention @Autoheal in a channel; it replies in the thread and can escalate to a full investigation |
| Agent-decided investigations | Ask it to investigate / look into / find the root cause and it starts a real investigation, threading results back to where you asked |
| 1:1 chat | Message the bot in a personal (1:1) chat for a private, persistent session — no mention needed |
| On-demand history recall | The agent can read earlier messages in the thread or channel to ground a follow-up question |
| Progress indicator | A "Working on it…" message posts the moment Autoheal picks up your request, then edits itself into the answer when the agent replies |
| Sender attribution | Chats you start are attributed to you and show up in your Autoheal /chats |
| Shareable deep links | Every chat and investigation carries a link back to the Autoheal web app |
Prerequisites
- A Microsoft Entra ID (Azure AD) tenant that has Microsoft Teams provisioned (any organizational plan from Teams Essentials up to M365 E5 — not the free/consumer tier).
- A tenant admin (Global Administrator or Privileged Role Administrator) to grant tenant consent.
- Permission to sideload / install a custom app into the target Team (or an admin to do it).
- Self-hosted (BYOC) only: rights to register an Azure Bot resource and an Entra app in your tenant.
Set up
How you connect depends on where Autoheal runs:
- Autoheal Cloud (SaaS) — connect the Autoheal-owned Teams app with tenant admin consent. Nothing to register, no credentials, and no authentication method to choose — Autoheal authenticates its own app.
- Self-hosted (BYOC) — register your own Azure Bot + Entra app and choose one of three authentication methods for how the Autoheal host proves it's that app: Client Secret, Managed Identity, or Workload Identity Federation.
Pick your deployment:
- Autoheal Cloud (SaaS)
- Self-hosted (BYOC)
On Autoheal Cloud you connect the Autoheal-owned multi-tenant Teams app with tenant admin consent — there are no credentials to enter and nothing to register in Azure. A tenant admin approves once; Autoheal authenticates its own app for you.
Prerequisites
- A tenant admin (Global Administrator) to approve the consent screen.
- Sideloading (custom app upload) allowed in your tenant (Teams admin center → Setup policies → Upload custom apps = On).
- Go to Integrations in Autoheal
- Click Microsoft Teams
- Click Connect — you're sent to Microsoft's admin-consent screen
- Sign in as a tenant admin and click Accept. Autoheal creates the integration once consent succeeds.
Add the Autoheal app to the Team where it should operate (Apps → Manage your apps → Upload / Add for the Autoheal app), and add it to a channel.
In that channel, @Autoheal <your question> — the bot replies in the thread.
Admin consent grants Autoheal's app the least-privilege Microsoft Graph application permissions it needs (Organization.Read.All to name the integration, User.Read.All to attribute chats to you). Channel-history recall additionally needs ChannelMessage.Read.All — see Limitations.
Self-hosted deployments register their own Azure Bot + Entra app in their Entra tenant, and choose how the Autoheal host authenticates that app. The auth method is a host/deployment setting — you set it once in the deployment .env, alongside the other TEAMS_* values. (Teams has a single bot per deployment, so the method is host-wide, not per-connection.)
Which method should I use?
| Your host | Recommended method | Secret stored? |
|---|---|---|
| Any cloud / on-prem, simplest path | Client Secret | Yes (rotate before expiry) |
| Azure VM or AKS | Managed Identity | No |
| AWS EKS, GKE, on-prem k8s, or Azure AKS (best practice) | Workload Identity Federation | No |
Managed Identity is Azure-only and single-tenant; Workload Identity Federation works on any host with an OIDC issuer (this is how a non-Azure host authenticates the Entra Teams app). Pick the tab that matches where Autoheal runs:
- Client Secret
- Managed Identity
- Workload Identity Federation
Works on any host (Azure, AWS, on-prem). The deployment holds the app's client secret and the bot password. Simplest to set up; the trade-off is you store secrets and rotate them before they expire.
Register in Azure
- An Entra app registration (single-tenant) with a client secret, granted the Graph application permissions (
Organization.Read.All,User.Read.All, andChannelMessage.Read.Allfor history) with admin consent. - An Azure Bot resource (app type Single-Tenant) with a client secret, the Microsoft Teams channel enabled, and its messaging endpoint set to
https://<your-host>/api/v1/webhooks/teams/messages.
Deployment .env
TEAMS_APP_AUTH_MODE=client_secret # or omit — this is the default
TEAMS_APP_CLIENT_ID=<entra-app-client-id>
TEAMS_APP_CLIENT_SECRET=<entra-app-secret>
TEAMS_BOT_APP_ID=<azure-bot-app-id>
TEAMS_BOT_APP_PASSWORD=<azure-bot-password>
TEAMS_BOT_SINGLE_TENANT=true # single-tenant bot
APP_BASE_URL=<your-host> # for the messaging endpoint + deep links
Azure hosts only (the host must reach the Azure Instance Metadata Service). Secretless and single-tenant — a good fit for BYOC on an Azure VM.
Register in Azure
- Create a user-assigned managed identity (or use the VM's system-assigned one) and attach it to the Autoheal host.
- Create the Azure Bot as app type User-Assigned Managed Identity, bound to that identity, with the Teams channel enabled and the messaging endpoint set as above.
- Grant the Graph application permissions to the managed identity's service principal. Managed identities have no "API permissions" blade in the Portal, so assign the app roles via script:
# assign Organization.Read.All / User.Read.All / ChannelMessage.Read.All to the MI's service principal
# (Graph: New-MgServicePrincipalAppRoleAssignment) — see Microsoft docs
Deployment .env
TEAMS_APP_AUTH_MODE=managed_identity
AZURE_BYOC_MANAGED_IDENTITY_CLIENT_ID=<user-assigned-mi-client-id> # omit for system-assigned
TEAMS_BOT_SINGLE_TENANT=true
APP_BASE_URL=<your-host>
Write the resolved GUID into .env — don't paste AZURE_BYOC_MANAGED_IDENTITY_CLIENT_ID=$(az identity show …) literally; .env isn't a shell. Managed Identity is Azure-only and single-tenant (the identity's own tenant).
Works on any host with an OIDC issuer — Azure AKS, AWS EKS, GKE, or on-prem k8s. Secretless: the host presents its projected identity token as a client_assertion, so no client secret is stored or rotated. This is the way to authenticate an Entra Teams app from a non-Azure host.
Register in Azure
- An Entra app registration with a Federated Identity Credential (no secret), granted the Graph application permissions with admin consent.
- An Azure Bot resource (app type Single-Tenant) whose underlying Entra app also carries a Federated Identity Credential, with the Teams channel enabled and the messaging endpoint set as above.
- Configure the federated credential to trust your host's OIDC issuer + service account:
- Azure AKS → the AKS OIDC issuer + the workload's service account.
- AWS EKS → the EKS cluster's OIDC provider + the pod's service account (this is what makes an AWS host → Entra app work).
Deployment .env
TEAMS_APP_AUTH_MODE=workload_identity_federation # auto-selected only if AZURE_FEDERATED_TOKEN_FILE is set AND no client secret is configured
AZURE_FEDERATED_TOKEN_FILE=/var/run/secrets/azure/tokens/azure-identity-token
TEAMS_APP_CLIENT_ID=<entra-app-client-id>
TEAMS_BOT_APP_ID=<azure-bot-app-id>
TEAMS_BOT_SINGLE_TENANT=true
APP_BASE_URL=<your-host>
Azure validates the assertion's iss / sub / aud against the federated credential, so they must match your host's projected token exactly. When TEAMS_APP_AUTH_MODE is unset, Autoheal auto-selects this mode only if a projected federated token file is present and no client secret is configured — set TEAMS_APP_AUTH_MODE explicitly to use WIF alongside a secret.
After the app/bot and .env are in place, restart Autoheal, then go to Integrations → Microsoft Teams → Connect, have a tenant admin grant consent, and install the app into a Team (as in the Autoheal Cloud tab).
How It Works
- In a channel:
@mentionthe bot with your question. It replies in the thread; each thread is its own session. Messages that don't mention the bot are ignored. - In a 1:1 chat: message the bot directly — no mention needed.
- Investigations: when you ask Autoheal to investigate, look into, or find the root cause of something, it starts a full investigation and threads the hypotheses, findings, and root-cause card back to where you asked.
- Acknowledgement: Autoheal posts a "Working on it…" card the instant it picks up your request and edits that same card into the answer, so you always know it's working.
- Alert routing: routing alerts and lifecycle updates to Teams channels arrives in a later release.
Usage Examples
In a channel where the bot is installed:
@Autoheal look into high latency on the payments API
@Autoheal what changed in the last deployment?
@Autoheal summarize what we've discussed in this thread
In a 1:1 chat (no mention needed):
which services are erroring right now?
Limitations
- Organizational Entra tenant required. Teams runs on Microsoft Entra + the Bot Framework; the free/consumer "Microsoft Teams" tier has no admin-consent-capable tenant and can't complete the connect flow.
- Channel-history recall needs a protected Graph API. Reading Teams channel messages uses
ChannelMessage.Read.All, a Microsoft protected API that requires access approval (and can be metered) — independent of the auth method. Connect and sender attribution (/organization,/users) are not protected and work in every mode. Until it's granted, the history tool returns a permission error and the agent falls back to asking you. - Managed Identity is Azure-only and single-tenant. It can't authenticate a multi-tenant app and needs Azure's metadata service, so it's a self-hosted-on-Azure option. Workload Identity Federation covers non-Azure hosts and is multi-tenant capable; Client Secret works anywhere.
- One Teams app per deployment. A deployment has a single bot, messaging endpoint, and auth mode. Multiple tenants can connect (SaaS), but they all flow through that one app.
- Auth mode is a deployment setting, not a per-connection UI choice. In BYOC you set it in the host
.env; there's no per-tenant auth-method dropdown (Teams' identity is host-wide, unlike the Azure DevOps integration).
Troubleshooting
Bot not responding in a channel
- Verify the Autoheal app is installed in the Team and added to the channel, and that you used
@Autoheal(a real mention) — non-mention messages are ignored in channels. - In a 1:1 chat, message the bot directly (no mention needed).
- Check that the Microsoft Teams integration shows as Connected in Autoheal.
Connect shows "Need admin approval"
Application permissions are tenant-wide and only a Global Administrator / Privileged Role Administrator can grant them. Sign in with an admin account on the consent screen (or have an admin pre-grant consent on the app), then retry Connect. A non-admin declining produces error=access_denied.
403 on Graph (sender attribution / history)
The app is missing an admin-consented Graph permission. Confirm User.Read.All (attribution) and ChannelMessage.Read.All (history) are granted. Managed Identity: these app roles must be assigned to the managed identity's service principal (via script — the Portal won't do it), or every Graph call 403s.
WIF: token mint fails with AADSTS70021
The Entra app's Federated Identity Credential issuer / subject / audience don't match the host's projected token, or it was just created. Re-check them against your host's OIDC issuer + service account, confirm AZURE_FEDERATED_TOKEN_FILE is mounted and readable, and retry shortly — propagation can take a few minutes.
Managed Identity: token mint / IMDS unreachable
Confirm the managed identity is attached to the Autoheal host and the host can reach 169.254.169.254. For a user-assigned identity, confirm AZURE_BYOC_MANAGED_IDENTITY_CLIENT_ID in .env is a concrete GUID (not a $(…) command) and that you restarted Autoheal. Managed Identity only works on Azure hosts.
History tool returns a permission error
Channel-message reads need ChannelMessage.Read.All, a protected Graph API. Request access through Microsoft and grant + admin-consent it; until then the agent asks you for the missing context instead of reading the thread.