Teams Bot
Setting up a Personal-Scope Teams Bot powered by a StackAI workflow
This guide walks through shipping a Microsoft Teams chatbot that:
Is pinned to the Teams left rail (looks and feels like Microsoft Copilot's side chat).
Receives every user message as a webhook trigger into a StackAI workflow.
Posts replies back into the same conversation thread.
End-to-end you will need:
An Azure subscription (or Pay-As-You-Go) and Microsoft 365 tenant where you can register apps.
Admin permission to upload custom Teams apps to your org (or at least to your own Teams account for sideloading).
A StackAI workspace with the Microsoft Teams Bot integration available.

Architecture at a glance
Three Microsoft pieces and one StackAI piece:
Microsoft Entra app registration — gives the bot an identity (App ID + client secret).
Azure Bot resource — registers the bot with Bot Framework and turns on the Teams channel.
Teams app manifest — declares a personal-scope bot so users can pin it.
StackAI workflow — the brain.
Step 1 — Register an Entra (Azure AD) application
This gives the bot its identity.
Go to Azure Portal → Microsoft Entra ID → App registrations → New registration.
Fill in:
Name: e.g.
StackAI Teams Bot.Supported account types: choose based on who should be able to use the bot:
"Single tenant" — only your org.
"Multi-tenant" — recommended if you'll distribute to other tenants.
Redirect URI: leave this field blank.
Click Register.
On the overview page, copy and save:
Application (client) ID → this is the App ID.
Directory (tenant) ID → this is the Tenant ID.
Go to Certificates & secrets → New client secret:
Description:
StackAI Bot.Expiry: 24 months (rotate before expiry).
Click Add, then immediately copy the Value (not the Secret ID). This is the Client Secret — Azure will never show it again.
Save these three values somewhere safe:
Step 2 — Create the Azure Bot resource
This is the Bot Framework registration that lets Teams talk to your bot endpoint.

In the Azure Portal, search Azure Bot → Create.
Fill in:
Bot handle: a unique name like
stackai-teams-bot-<orgname>.Subscription and Resource group: pick or create.
Pricing tier:
F0(free) is fine for development; useS1for production.Type of App: Multi Tenant (or Single Tenant — must match what you chose in Step 1).
Creation type: Use existing app registration.
App ID: paste the App ID from Step 1.
Click Review + create → Create. Wait for deployment.
After deployment, open the new Azure Bot resource. You'll point its messaging endpoint at StackAI in Step 4.
Go to the bot's Channels blade in Settings → click Microsoft Teams → accept terms → Apply.
In the same Channels tab, you should see the Teams channel show Healthy.
Step 3 — Create the connection in StackAI
Before configuring the messaging endpoint, you need the StackAI bot connection so you can grab its webhook URL.
In StackAI, open Integrations → Microsoft Teams Bot → Connect.
Fill in:
App ID → from Step 1.
Client Secret → from Step 1.
Tenant ID → from Step 1 (use
commonif you registered the app as multi-tenant and want it to work across tenants).
Save the connection. StackAI will validate the credentials by minting a Bot Framework token.
Keep this tab open — you'll come back to it once the workflow trigger exists.
Step 4 — Build the StackAI workflow
The workflow is the brain. At minimum it needs a Teams trigger and a Teams reply action.
4a. Create the workflow
In StackAI, New Project → blank workflow.
Add a Trigger node → choose Microsoft Teams Bot → On New Teams Message.
Select the connection you created in Step 3.
Save.
Tip: if you want the bot to respond only when @mentioned in a channel, use the On Bot Mentioned trigger instead. For 1:1 personal chat, On New Teams Message is correct.
Add an LLM node (or whatever workflow logic you want).
Pipe the trigger's
message_textinto the prompt.Other useful trigger fields:
conversation_id,sender_id,service_url,activity_id.
Add an action node → Microsoft Teams Bot → Reply to Message.
Connection: same as the trigger.
Conversation ID, Service URL, Reply to Activity ID: map from the trigger output. The integration uses these to thread the reply correctly.
Message: pipe in the LLM output.
Save and publish the workflow.
4b. Wire the messaging endpoint to Azure Bot
The Microsoft Teams Bot integration uses a shared, fixed webhook URL for every Teams bot — there is no per-trigger URL generated in the StackAI UI. StackAI routes each inbound activity to the correct workflow using the App ID / Tenant ID on your connection (Step 3).
Back in the Azure Portal → your Azure Bot resource → Settings → Configuration.
Messaging endpoint: paste this URL exactly:
Click Apply.
Azure will now send every Teams Activity (message, mention, etc.) to that URL, and StackAI will dispatch each one to the workflow whose connection matches the bot's App ID.
Step 5 — Create the Teams app manifest
This is what makes the bot show up as a pinnable personal app in Teams. The easiest path is Teams Developer Portal.
Go to https://dev.teams.microsoft.com → Apps → New app.
Give it a name (
StackAI Assistantworks) → Add.Under Basic information, fill in:
App ID: click the dice icon to generate a new GUID (this is the Teams app ID — different from the Bot App ID).
Short / long descriptions.
Developer info, Website, Privacy / TOS URLs (required even for internal apps — point at any reachable HTTPS page).
App icons: 192×192 color + 32×32 outline. Required.
Under App features → Bot → Create new bot (or pick existing):
When prompted for a Bot ID, paste the App ID from Step 1 (the Entra app — same one used by your Azure Bot resource).
Scope: enable Personal (and Team / Group chat if you also want it usable in those contexts).
Save.
Manifest sanity check
Under App features → Bot, verify:
Bot ID = your Entra App ID.
Personal scope is checked.
You can also add a Personal app tab here if you want a separate web tab next to the chat — not required for the Copilot-style chat experience.
Step 6 — Install the app in Teams
Option A: Sideload for yourself (fastest for testing)
In Teams Developer Portal, click Preview in Teams (top right) on your app.
Teams opens with an install prompt → click Add.
The bot appears in your left rail. Right-click → Pin so it stays.
Option B: Deploy across your organization
This is the production path: a Microsoft 365 admin uploads the bot to your tenant's app catalog and uses App Setup Policies to auto-install and pin it for the right audience — either everyone in the tenant or a specific subgroup (a department, an Entra security group, a pilot team).
You will need a user with one of these roles in your tenant:
Teams Administrator (or Global Administrator) for app upload and policy changes.
Groups Administrator (or User Administrator) if you need to create the security/M365 group used to scope the rollout.
B1. Submit the app via Dev Portal
In Teams Developer Portal (https://dev.teams.microsoft.com) open your app.
Top right → Distribute → Publish to your org.
Confirm. The app is sent to your tenant's review queue in Teams Admin Center.
Alternative: if you'd rather skip the review queue, click Download app package instead and upload the
.zipdirectly via Teams Admin Center → Manage apps → Actions → Upload new app. End state is the same. Most users find Distribute easier because they don't have to manage a.zipfile or remember which Teams Admin Center menu to use.
B2. Approve and unblock the app in Teams Admin Center
Heads up: Teams Admin Center has two independent statuses for every app, and you have to clear both. This trips up almost everyone.
A freshly distributed app typically lands as Submitted + Blocked. You need to publish it (B2.4) and unblock it (B2.5) before users can get it. An app that is Published but Blocked will look approved in the admin UI but will be invisible / un-installable for end users.
Publishing status
Submitted / Published
Whether the app exists in your tenant's catalog
Status
Allowed / Blocked
Whether users are permitted to install/use it
Go to Teams Admin Center → https://admin.teams.microsoft.com.
Left nav → Teams apps → Manage apps.
Filter by Publishing status: Submitted (or look for the yellow Pending publish badge on your app).
Click your app → Publish button → confirm. Publishing status flips to Published.
Unblock the app:
On the app's page, find the Status toggle (top of the page or in the Availability section).
Set it to Allowed. If it's already Allowed, leave it.
Permissions tab → if any permissions are listed, click Grant admin consent.
If unblocking the app didn't help
There are two more places that can block a custom app even after the per-app Status is Allowed:
Org-wide app settings (tenant-level kill switch):
Still in Manage apps, top right → Org-wide app settings.
Under Custom apps → ensure Let users interact with custom apps is On.
Under Third-party apps → ensure custom-app interaction isn't disabled there.
Save.
App permission policies (per-user app gating):
Teams apps → Permission policies.
Open the policy assigned to your target user (Global / Org-wide default unless you've made custom ones).
Under Custom apps, ensure it's Allow all apps, or add your specific app to the allowed list.
Most enterprise tenants block custom apps by default for security, so expect to flip at least the per-app Status. The org-wide and permission-policy layers are only an issue in tighter security configurations.
At this point the bot exists in the tenant catalog and is unblocked, but nobody has it installed yet. Distribution to users happens via App Setup Policies (next step).
B3. Decide your audience
Pick one before you touch policies:
Everyone in the tenant
Modify the Global (Org-wide default) setup policy
A specific department / team
Create a new custom setup policy, then assign it
A pilot group of named users
Create a new custom setup policy, then assign it
For department/group rollouts, make sure the group exists in Entra ID first:
Entra Admin Center → Groups → New group.
Group type: Security (cheapest) or Microsoft 365 (if you want a shared mailbox too).
Membership type: Assigned for static lists, Dynamic User for rule-based (e.g.
department -eq "Customer Success").Add the members. Note the Object ID — you'll reference this group from the Teams policy.
B4. Create or edit the App Setup Policy
A setup policy controls which apps are pre-installed and which apps are pinned to the left rail. You need entries in both sections — installing without pinning means users have to dig through "More apps" to find the bot, which kills adoption.
Teams Admin Center → Teams apps → Setup policies.
Either:
Edit Global (Org-wide default) → applies to every user not covered by a custom policy.
Add a new custom policy → name it (
StackAI Bot Pilot,Customer Success Bots, etc.).
Under Installed apps → Add apps:
Search your app name → Add → Add.
This makes Teams silently install the app for assigned users on next launch.
Under Pinned apps → Add apps:
Search your app name → Add → Add.
Drag it to the position you want in the left rail. Top-of-list gets the most usage; below the bottom edge gets ignored.
User pinning: leave on (recommended) so users can re-pin if they accidentally remove it. Turn it off if you want to lock the rail layout.
Save.
Changes propagate to clients within ~24 hours; usually much faster (5–60 min).
B5. Assign the policy to your audience
Skip this step if you edited the Global (Org-wide default) policy — it already applies to everyone.
For a custom policy, assign it one of two ways:
Per-user (small lists):
Teams Admin Center → Users → Manage users.
Filter / select the users.
Edit settings → App setup policy → pick your custom policy → Apply.
Per group (recommended for any rollout > ~10 people):
Teams Admin Center → Teams apps → Setup policies → Group policy assignment tab.
Add group assignment.
Pick the Entra group from B3, choose App setup policy, pick your policy, set rank (lower number = higher priority if a user is in multiple groups).
Apply.
Group assignment is rank-based: each user gets the highest-priority policy they're eligible for. Per-user assignment beats group assignment beats global default.
B6. Verify the rollout
Pick a sample user in the audience. Have them quit and reopen Teams (or wait up to 24h).
The bot should appear pinned in their left rail with no action on their part.
As admin, run Teams Admin Center → Users → [user] → Policies tab to confirm the right setup policy is effective for that user.
Check Manage apps → [your app] → Usage after 24h to see DAU/MAU per the rollout audience.
B7. Shipping updates
When you change the manifest (new icon, new bot name, new scopes):
In Teams Developer Portal, bump the Version field on the app's basic information page (semver —
1.0.0→1.0.1).Click Distribute → Publish to your org again.
In Teams Admin Center → Manage apps, find the app and approve the new version.
No policy changes needed — installed users get the new version automatically.
When you change only the workflow logic in StackAI (most common case): nothing to redeploy. The Teams app and Azure Bot are unchanged; users just get the new behavior on the next message.
Common org-wide gotchas
Some users don't see the bot pinned
They have a higher-priority custom policy without your bot in it
Add the bot to that policy too, or rank yours above it
Bot installed but not pinned
Policy has Installed apps entry but missing Pinned apps entry
Add to Pinned apps in the same policy
App is Published but users still can't install or see it
App's Status is Blocked (default for newly published custom apps)
Manage apps → your app → toggle Status: Allowed
Per-app Status is Allowed but app still blocked for users
Tenant-wide custom-app block, or restrictive App Permission Policy
Manage apps → Org-wide app settings → enable custom apps; check Permission policies for the user's policy
429 / throttling under load
Azure Bot still on F0 tier
Upgrade Azure Bot resource to S1 before broad rollout
Updates not reaching users
Manifest version not bumped
Always increment Version in Dev Portal before re-distributing
Pilot group rolls out to everyone
Custom policy not assigned to a group; only Global policy was edited
Assign custom policy via Group policy assignment and confirm Global policy is unchanged
Recommended rollout pattern
You only (sideload, Option A) — verify the workflow end-to-end.
5-person pilot — custom setup policy assigned to a small Entra group of friendlies. Run for a week, gather feedback, fix prompts.
Department — assign the same policy to a larger Entra group (e.g.
Customer Successdynamic group). Run for 2–4 weeks.Org-wide — add the bot to the Global setup policy. Retire the pilot policy or keep it for staging changes ahead of the global rollout.
The "feels like Copilot" effect comes entirely from B4's pinning step — without it, users have to find the app manually and adoption craters.
Step 7 — End-to-end smoke test
In Teams, click the pinned app icon → opens a 1:1 chat panel.
Type "hello".
Watch:
Azure Bot → Test in Web Chat logs.
StackAI → run history for the workflow. You should see a run triggered with the message text.
The reply should land back in Teams within a couple of seconds.
If something is off, see troubleshooting below.
Common gotchas
StackAI run never triggers
Messaging endpoint URL wrong, or Teams channel not enabled on the Azure Bot
Re-paste the StackAI webhook URL exactly; confirm the Teams channel shows Running
401 Unauthorized on inbound
Tenant ID mismatch between Entra app and StackAI connection
For multi-tenant bots use common as the StackAI Tenant ID; for single-tenant use the actual tenant GUID
Reply action fails with Unauthorized
Client secret expired or wrong
Generate a new secret in Entra → update the StackAI connection
Bot never appears in left rail
Org policy doesn't allow custom apps, or app not pinned
Have admin enable custom app sideloading and add a pin policy
Reply lands in a new thread instead of replying inline
Action isn't getting reply_to_activity_id
Check the field mapping from trigger output → Reply to Message action
Works in personal chat but not in channels
Channel scope not enabled on manifest, or you're using the wrong trigger
Add Team scope to manifest, switch trigger to On Bot Mentioned
Slow first response after long idle
Bot Framework token cache cold start
Expected; subsequent replies are fast
Production checklist
Before rolling out to users:
Quick reference
App ID, Tenant ID, Client Secret
Microsoft Entra ID → App registrations
Messaging endpoint
Azure Portal → Azure Bot → Configuration
Teams channel toggle
Azure Portal → Azure Bot → Channels
StackAI trigger webhook URL
StackAI workflow → Trigger node → "On New Teams Message"
Pinning policy
Teams Admin Center → Teams apps → Setup policies
Manifest editor
Last updated
Was this helpful?

