Microsoft Teams Bot
Integrate Microsoft Teams as an interaction surface for Atlas with Bot Framework messaging and Adaptive Cards.
@useatlas/teams is deprecated. Use @useatlas/chat with the Teams adapter instead.
The Chat SDK bridge plugin provides the same Teams functionality plus multi-platform support (Slack, Discord, etc.) and built-in state management. See the migration guide below.
The Teams interaction plugin integrates Microsoft Teams as an interaction surface for Atlas. Users can @mention the bot in channels or send direct messages, and the bot replies with Adaptive Cards containing formatted query results, SQL, and data tables.
This plugin uses the routes() interface to mount Hono routes directly into the Atlas API server, and receives runtime dependencies (agent execution, rate limiting) via config callbacks rather than importing from @atlas/api.
Installation
bun add @useatlas/teamsPrerequisites
- An Azure Bot registration with Microsoft App ID and App Password
- The bot registered in a Teams app manifest
- A publicly accessible endpoint for the Bot Framework messaging webhook
Azure Bot Registration
1. Create an Azure Bot resource
- Go to the Azure Portal
- Search for Azure Bot and create a new resource
- Choose Multi Tenant for the bot type (or Single Tenant if restricting to one Microsoft Entra ID tenant)
- Note the Microsoft App ID — this is your
appId
2. Create an App Password
- In the Azure Bot resource, go to Configuration
- Click Manage Password next to the Microsoft App ID
- Click New client secret and note the value — this is your
appPassword
The App Password is only shown once. Copy it immediately and store it securely. If lost, create a new one.
3. Configure the messaging endpoint
Set the Messaging endpoint to your Atlas API's Teams messages route:
https://your-atlas-api.example.com/api/plugins/teams-interaction/messages4. Enable the Teams channel
In the Azure Bot resource, go to Channels and add Microsoft Teams.
5. Create a Teams app manifest
Create a Teams app with the bot capability pointing to your Azure Bot registration. You can use the Teams Developer Portal to create and install the app.
Configuration
import { defineConfig } from "@atlas/api/lib/config";
import { executeAgentQuery } from "@atlas/api/lib/agent-query";
import { teamsPlugin } from "@useatlas/teams";
export default defineConfig({
plugins: [
teamsPlugin({
appId: process.env.TEAMS_APP_ID!,
appPassword: process.env.TEAMS_APP_PASSWORD!,
executeQuery: executeAgentQuery,
}),
],
});With optional tenant restriction and rate limiting:
export default defineConfig({
plugins: [
teamsPlugin({
appId: process.env.TEAMS_APP_ID!,
appPassword: process.env.TEAMS_APP_PASSWORD!,
tenantId: process.env.TEAMS_TENANT_ID,
executeQuery: executeAgentQuery,
checkRateLimit: myRateLimiter,
}),
],
});Options
| Option | Type | Required | Description |
|---|---|---|---|
appId | string | Yes | Microsoft App ID from your Azure Bot registration. |
appPassword | string | Yes | Microsoft App Password (client secret) from Microsoft Entra ID. |
tenantId | string | No | Restrict the bot to a specific Microsoft Entra ID tenant. Tokens from other tenants are rejected. |
executeQuery | function | Yes | Callback that runs the Atlas agent on a question and returns structured results. |
checkRateLimit | function | No | Optional rate limiting callback. |
scrubError | function | No | Optional error scrubbing callback to strip sensitive information from error messages. |
Mounted Routes
The plugin mounts the following Hono route under the plugin's base path:
| Method | Path | Description |
|---|---|---|
POST | /messages | Bot Framework messaging endpoint — receives all activities from Teams |
How It Works
- A user @mentions the bot or sends a direct message in Teams
- Teams sends a Bot Framework activity to the
/messagesendpoint - The plugin verifies the JWT in the Authorization header against Microsoft Entra ID's public keys
- The bot's @mention is stripped from the message text to extract the query
- The
executeQuerycallback runs the Atlas agent - Results are formatted as an Adaptive Card with answer, SQL, and data table
- The reply is sent back via the Bot Connector API
The executeQuery callback is the bridge between the Teams plugin and the Atlas agent. It receives the user's question, runs the agent, and returns structured results that the plugin formats into Adaptive Cards.
Environment Variables
| Variable | Description |
|---|---|
TEAMS_APP_ID | Microsoft App ID |
TEAMS_APP_PASSWORD | Microsoft App Password |
TEAMS_TENANT_ID | Optional Microsoft Entra ID tenant ID |
Troubleshooting
Bot not responding to messages
Verify the messaging endpoint URL in your Azure Bot Configuration matches your Atlas API's Teams route. For local development, use a tunnel service like ngrok or dev tunnels (devtunnel).
Authorization failures
Ensure TEAMS_APP_ID and TEAMS_APP_PASSWORD match the Azure Bot registration credentials. If using tenant restriction, verify the tenant ID matches the Microsoft Entra ID tenant where Teams is configured.
Adaptive Cards not rendering
Teams requires Adaptive Card schema version 1.5 or lower. The plugin uses version 1.5 which is supported by all current Teams clients.
Migrating to @useatlas/chat
Replace @useatlas/teams with the Chat SDK bridge plugin:
// Before:
import { teamsPlugin } from "@useatlas/teams";
teamsPlugin({ appId: "...", appPassword: "...", executeQuery })
// After:
import { chatPlugin } from "@useatlas/chat";
chatPlugin({
adapters: {
teams: { appId: "...", appPassword: "...", tenantId: "..." },
},
executeQuery,
})When using the Chat SDK bridge, update the messaging endpoint in your Azure Bot Configuration to:
https://your-atlas-api.example.com/api/plugins/chat-interaction/webhooks/teams| Feature | @useatlas/teams | @useatlas/chat |
|---|---|---|
| Webhook | /messages | /webhooks/teams |
| Adaptive Cards | Hand-rolled builders | Automatic via Chat SDK |
| State | None | State adapter (memory/PG/Redis) |
| Follow-ups | Single query per activity | Chat SDK subscription model |
| Multi-platform | Teams only | Teams, Slack, Discord, etc. |