Microsoft Teams Integration
Connect Microsoft Teams to work with Autoheal from your channels. @mention the bot to ask a question or start an investigation, and it replies in the thread. Autoheal answers conversationally by default. It starts a full investigation when you ask it to look into something. (Routing alerts to Teams channels is coming soon.)
Teams runs on Microsoft Entra ID (Azure AD) and the Bot Framework. To connect, you need 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 agents can do
Once connected, agents 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 | Agents 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 receives 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 |
Write tools on this integration (send and update messages) are available only to agents granted write access to it. A governance policy on write operations pauses each write for a person to approve, and every call is recorded in the Audit Trail.
Prerequisites
- A Microsoft Entra ID (Azure AD) tenant that has Microsoft Teams provisioned. Any organizational plan from Teams Essentials up to M365 E5 works. The free/consumer tier does not.
- 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).
- 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:
- 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.
- BYOC — register your own Azure Bot + Entra app. Then 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:
- SaaS
- BYOC
On SaaS 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). Then add it to a channel.
In that channel, send @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.ReadBasic.All to attribute chats to you). Channel-history recall uses the resource-specific permission ChannelMessage.Read.Group, which the team grants when the Autoheal app is installed into it. It covers only the teams the app is installed in. See Limitations.
BYOC 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. This is the simplest method to configure. The trade-off is that 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.ReadBasic.All) with admin consent. For channel history, the Teams app manifest'swebApplicationInfo.idmust be this app's client ID, and the manifest must declare theChannelMessage.Read.Groupresource-specific permission (see Limitations). - 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. Enable the Teams channel and set the messaging endpoint 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.ReadBasic.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. Do not paste AZURE_BYOC_MANAGED_IDENTITY_CLIENT_ID=$(az identity show …) literally. .env is not 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. Enable its Teams channel and set the messaging endpoint 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. To use WIF alongside a secret, set TEAMS_APP_AUTH_MODE explicitly.
After the app/bot and .env are in place:
- Restart Autoheal.
- Go to Integrations → Microsoft Teams → Connect.
- Have a tenant admin grant consent.
- Install the app into a Team (as in the SaaS 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. It threads the hypotheses, findings, and root-cause card back to where you asked.
- Acknowledgement: Autoheal posts a "Working on it…" card the instant it receives your request. It then edits that same card into the answer, so you always know it's working.
- Alert routing: routing alerts and lifecycle updates to Teams channels (coming soon).
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 is scoped per team. Reading Teams channel messages uses
ChannelMessage.Read.Group, a resource-specific consent (RSC) permission. It's declared in the Teams app manifest, not granted through Entra admin consent. The team grants it when the Autoheal app is installed into that team, and the app can read only channels in teams where it's installed. Self-hosted Teams app packages declare it like this:"webApplicationInfo": { "id": "<graph-client-id>", "resource": "https://autoheal" },
"authorization": {
"permissions": {
"resourceSpecific": [{ "name": "ChannelMessage.Read.Group", "type": "Application" }]
}
}webApplicationInfo.idmust be the client ID Autoheal requests Graph tokens as, because Microsoft keys the team's grant to that ID. That'sTEAMS_APP_CLIENT_ID.resourceis required but unused by RSC, so any non-empty string works.- The
authorization.permissions.resourceSpecificblock needs app manifest schema v1.12 or later. Older schemas declare RSC permissions inwebApplicationInfo.applicationPermissionsinstead. - Install the app into the team (Manage team → Apps). Adding it only to a chat or a personal scope never grants
ChannelMessage.Read.Group.
If your tenant's team RSC setting is
DisabledForAllApps, the history tool returns a permission error. It does the same if the app was installed before the permission was added. In both cases, agents ask you for the context instead. -
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 an option only for BYOC on Azure. 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
- Check that the Autoheal app is installed in the Team and added to the channel. Check that you used
@Autoheal(a real mention). In channels, the bot ignores messages that do not mention it. - 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. Check that User.ReadBasic.All (attribution) is admin-consented. For history, check that the team granted ChannelMessage.Read.Group at install (see below). Managed Identity: assign these app roles to the managed identity's service principal (via script — the Portal won't do it). Otherwise 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.
- Check that
AZURE_FEDERATED_TOKEN_FILEis mounted and readable. - Retry shortly. Propagation can take a few minutes.
Managed Identity: token mint / IMDS unreachable
Check that the managed identity is attached to the Autoheal host and the host can reach 169.254.169.254. For a user-assigned identity, check that 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 the ChannelMessage.Read.Group resource-specific permission for that team. Check that the Autoheal app is installed in the team, not just added to a chat, and that its manifest declares the permission. If the app was installed before the permission was added, update or reinstall it so the team can consent. Also check that a Teams admin hasn't set the tenant's team RSC state to DisabledForAllApps. This state is managed with Set-MgBetaTeamRscConfiguration. The default, ManagedByMicrosoft, allows it. Until the permission is granted, agents ask you for the missing context instead of reading the thread.