M365 Show -  Microsoft 365 Digital Workplace Daily
M365 Show with Mirko Peters - Microsoft 365 Digital Workplace Daily
Building Custom Teams Apps with Bots, Tabs, and Message Extensions
0:00
-19:35

Building Custom Teams Apps with Bots, Tabs, and Message Extensions

If you’ve ever wanted to cut out five different clicks just to fetch key data during a Teams chat, you’re in the right place. Message extensions are the shortcut you didn’t know you needed—but which type actually fits your workflow?
Today, we’re exposing the real differences between Teams search, action, and link unfurling extensions. Plus, I’ll walk you through building an action-based one that pulls external data straight into your conversations, no context-switching required.

Why Message Extensions Are the Most Overlooked Productivity Power-Up

Everyone talks about bots and tabs in Teams. The search bar gets an entire page of tutorials. But the average user—especially outside of IT—misses what message extensions actually unlock. If you think of all the time you spend bouncing between apps, pasting in updates, or trying to grab some live data for your team, it’s easy to see why these other features get most of the attention. They’re showy. They sit in obvious places in the menu. They look interactive. But look a little closer, and you’ll realize there’s a hidden tool in plain sight that handles so much of the tedious work nobody wants to do.

Let’s say your day starts with a simple request: someone in chat asks for the latest sales number, or a customer’s support history. Maybe you’re forced to open the CRM in a separate browser, dig up the record, then painstakingly copy the information back into Teams. Ten minutes gone, and that conversation has already moved on. Multiply that by five or six requests per day and you’ve basically lost an hour without even thinking about it. We’ve all been there—scrambling to keep up because the process for sharing information breaks your flow. There are tabs and bots that promise a fix, but they all seem to demand an extra step, or open another window, and soon you’re managing as many browser tabs as real conversations.

Here’s the funny part: even the biggest Teams fans rarely open up the message extension menu. Most assume, “I’ll just ask the bot”—never mind that bots love to demand very specific commands, or throw an error if you phrase something the wrong way. Tabs sound good in theory but pull you into a full app view, swallowing up what’s happening in the chat. Somewhere in between, message extensions are sitting there like a Swiss Army knife. They’re not flashy, and their little icon gets overshadowed by the stack of notifications everyone is staring at instead. But when you actually need to move information from one place to another without leaving the chat window, nothing comes close.

Take a sales team as an example. Every time an account manager needs to update the pipeline, it’s the same ritual—switching out of Teams, logging into Salesforce, pulling up an ID, then bouncing back to paste a number. Replace “Salesforce” with whatever system your own department clings to, and the problem is the same. For support teams, you see it when someone needs to drop in a ticket update for a customer’s incident, and suddenly they’re toggling between ServiceNow, their Outlook, Slack, and finally, back to Teams. Even project managers aren’t safe: status reports, budget numbers, or the latest deadline get lost in the scroll of half a dozen browser tabs.

What’s fascinating is just how invisible message extensions are, even though Microsoft data shows the adoption rate lags far behind that of bots and tabs. Most users don’t explore that extra little more menu beside the chat box, and admin training rarely covers what extensions can do. The numbers paint a clear story: people default to whatever feature sits on the main screen, clicking anything else only when prompted or called out during onboarding. So the bulk of communication remains manual, dependent on human memory and the hope that someone pastes the right data in the right format whenever it’s needed.

Maybe the biggest missed opportunity is time itself. It’s easy to hand-wave a few seconds lost copying and pasting, but context switching adds up fast. Multiple research studies put the cost of switching tasks anywhere from 20 to 30 minutes per day for heavy Teams users, a number that jumps higher in roles that depend on live information. That’s not just wasted time, it’s decision fatigue—people forget what they were working on, lose their place in a conversation, and sometimes miss a critical piece of data they were trying to share in the first place.

Here’s the real question, though: if message extensions can reduce all that friction, why aren’t they at the top of every admin’s adoption list? The answer usually comes down to visibility and awareness, not usefulness. Once you get into the habit, interacting with data right inside the conversation feels natural—and the effect is immediate. With message extensions, you aren’t just dropping links; you’re letting users trigger a live data lookup, fill out a quick form, or share a customer profile, all without ever clicking away.

So, if message extensions can do everything from surfacing records to spinning up interactive updates, you’re probably wondering what kinds actually exist. Because not all message extensions are created equal—and picking the right type is what determines whether your team finally gets out from under the copy-paste treadmill or just adds another button nobody uses.

Choosing the Right Tool: Comparing Search, Action, and Link Unfurling Extensions

The reality is, most Teams admins see “message extension” and assume it’s just one big monolith—turn it on, let folks explore, and call it a day. But the details matter here. Using the wrong message extension type doesn’t just create a learning curve, it builds in confusion from day one. People start expecting everything to behave like a search box, only to realize halfway through a workflow that things just…stop. Or they click a button expecting a quick preview and get a mini app trying to collect their email for the third time that day. It’s the difference between a workflow that runs smoothly, and one that has users asking, “Why can’t Teams just do what I want?”

Teams groups message extensions into three flavors. First, you’ve got the search extension. This is the one you see when someone clicks the “...” below the chat box and starts typing for a record or document. Think of it like a Teams-native search with direct tie-ins: the sales rep types the customer’s name, instantly pulls up the latest deal, and shares it to chat in a couple of clicks. Then you have action extensions. These are a bit more involved. Instead of just finding something, they let users fill out a form, trigger a backend process, or gather feedback. A good example? The HR manager drops in a quick “request vacation” button, and users fill out the dates right there—submitting the form without leaving the thread. And finally, there’s link unfurling. The most “invisible” of the bunch—paste a CRM link, and instead of dumping a long blue URL into chat, Teams turns it into a rich summary with the deal stage, client name, and even a contact photo. Each looks simple in the UI. Dig deeper, and they’re solving completely different problems.

Here’s where it gets tricky. If your team just needs information surfaced—for example, the latest sales lead or a recent support ticket—search extensions do the job. Instantly surfacing data, no complicated workflows. But let’s say you need to do more than surface info. Someone needs to approve a budget, create a new service request, or collect structured feedback right where the discussion is happening. That’s the territory of action extensions. They collect details, pass them to your backend, and then let you show a summary directly in chat. No separate tabs, no copy-paste. With link unfurling, the scenario is different. It’s all about making pasted links smarter. You want someone to share a CRM deal, and instead of a cold hyperlink, give that context—status, owner, priority—all displayed as soon as the link hits the chat. For a user, it feels almost magical, but for the admin, it’s a conscious choice: what experience do you want to enable?

Imagine the same scenario—“I need the status of Order #4421.” With a search extension, the user types the order number, and the extension pops up with the latest info. With an action extension, maybe someone needs to file a follow-up request, attach a screenshot, or note a delivery issue—they get a mini form, submit it, and the conversation moves on. If someone pastes a URL from the order system, link unfurling kicks in, turning that bare link into a product summary or package tracking widget. Three routes to the same conversation, but three different outcomes.

Now, not every type is frictionless. Permissions can trip up the rollout fast. Search and action extensions often need to connect to backend systems. That means OAuth, SSO, or—worst case—the endless “consent to this app?” popups. Data privacy enters the mix, especially when you’re pulling customer info or financial data straight into chat. The most seamless extension in the world falls flat if the security team gets nervous about leaking sensitive details, or if you forget to scope permissions tight enough for each team.

Authentication can also create a hidden hurdle. Users expect instant results, but backend systems aren’t always tied into Azure AD cleanly. You end up building (and debugging) authentication logic for each service, balancing privacy, speed, and user patience. With link unfurling, the privacy challenge is different—how much should you show in the chat preview? Just a title, or the entire customer record? Set that wrong, and now users see confidential info appear where it shouldn’t.

All this means that choosing the right type of message extension affects not just usability, but compliance and adoption down the road. Pick search where your users simply need a fast lookup. Deploy action extensions where input, workflow, or updates are part of the process. Roll out link unfurling when context matters more than workflows.

The right message extension transforms chat from a noisy backchannel into a real decision hub. When you tailor the tool to the job, Teams isn’t just driving faster conversations—it’s powering smarter ones.

That brings us to the heavy lifters: action-based message extensions. If you want to accelerate workflows and cut out manual steps, this is where the real payoff starts.

Inside the Swiss Army Knife: Building an Action-Based Message Extension That Does the Heavy Lifting

Let’s look at what actually happens in the middle of a busy Teams chat. Someone asks for a live update about a client order that just shipped, or a project manager wants the status of a critical task. Conventional wisdom tells you to open another tab, hunt for the data in a separate app, copy it all, and then alt-tab back to Teams to share the details. The reality is, by the time you’ve finished all that, half the team has checked out of the conversation. Manual copy-paste is a breeding ground for simple mistakes, like pasting the status for the wrong customer or missing the right context entirely. Bots force you into oddly specific commands, and tabs move the whole workflow away from the conversation. Neither fits the rhythm of fast, high-stakes collaboration.

Action-based message extensions break that snarl of interruptions by letting you stay exactly where the conversation is happening. You don’t have to jump between windows or remember a list of trigger phrases; you just click, fill in some details, and the answer lands right in the chat thread. What you’re really building is a workflow tool that starts and finishes within the context of your Teams discussion—no extra clicks, no losing the thread.

Here’s how the pieces fit together. The Microsoft Teams SDK is your starting point. It gives you the hooks to surface your extension’s button in the right places and handle the interactions with users. When someone clicks the action, Teams calls your extension, which usually sits behind a Bot Framework endpoint. The Bot Framework is where the real logic happens—it receives requests from Teams, passes along any user input, talks to your backend systems, and figures out what to send back. The adaptive card, that visually rich block you see embedded in chat, is generated in the backend and pushed back through the Bot Framework API. The SDK glues it all together so anyone can interact with the data, respond directly, or take another action, all in a two-step process that mimics natural conversation, not rigid forms.

Setting up your first action extension starts with registering a new Teams app in the Azure portal. Give it a manifest, pick your icon, and define the action handlers—these are the pieces of code that trigger when a user picks your extension from the Teams compose box. The manifest file is the contract that tells Teams where your backend lives, what permissions you need, and how the extension should display. If you want to hit external services (maybe your order database or CRM), this is the place you call out the right OAuth permissions and scopes.

On the backend, wiring up the Bot Framework means spinning up a simple web service. In Node.js, you might use the BotBuilder SDK; for .NET, it’s the Bot Framework SDK for C#. Your handler listens for requests Teams sends when the user activates the extension. Let’s say you have a “check order status” extension. A user clicks the extension, types in an order number, and Teams ships that info to your Bot. Your backend handler queries the order database, builds an adaptive card with live tracking details, and returns it to Teams, which inserts it right into the message thread.

Why adaptive cards? Plain text gets lost in the chat sea, and pasted screenshots get out of date in no time. Adaptive cards bring structure—sections, buttons, bold highlights, even embedded images—and let users interact without ever leaving Teams. You can make the data editable: Let a manager approve a request, update a deadline, or drop a comment, right inside the card. Suddenly, the conversation isn’t just a log of what people said—it’s part of the live workflow, updated in real time and readable at a glance.

It’s surprising how natural this ends up feeling. The button you add for “Order Status” becomes a muscle memory move. Within two clicks, anyone in chat—regardless of their backend access—can see the latest from the database, confirm delivery, or follow up with a client. The gap between inquiry and action closes almost overnight. You’re not waiting for someone to paste a screenshot or summarize a dozen emails. The card lands in the chat with up-to-the-minute data, and you move on. Every manual step that teams used to stumble over just fades away.

Of course, this is where things start to get interesting. You’ve built a working extension on your dev tenant and impressed a handful of testers, but making it available to the entire org—or worse, across multiple tenants—raises a new set of challenges. That’s when deployment, security, and discoverability take center stage. The story changes from what’s technically possible to what scales without blowing up your admin team’s weekend. And that’s a different kind of problem, with its own set of pitfalls to navigate.

Packaging, Deploying, and Scaling: Getting Your Extension into Users’ Hands

Here’s the part most developers quietly dread: taking that shiny Teams extension you’ve polished in the dev tenant and turning it into something the entire org can use without breaking into a cold sweat over permissions or compliance. Getting apps working for a handful of users is one thing. Shipping them to hundreds—or entire partner organizations in a multi-tenant setup—is where technical details meet real-world roadblocks. It’s never just about the code. Secure packaging, compliance checks, and making sure people can actually find your app matter just as much, sometimes more.

When you start packaging your extension, every little requirement along the way has ripple effects. You’ll be dealing with the Teams app manifest, which is more than a bit of required XML—it’s the literal handshake between your app and Teams. The manifest defines metadata, permissions, valid domains, endpoints, and where your extension’s icon appears. Even the icon needs care: Teams is picky about formats and sizes. Get the manifest or branding wrong and your app will fail to upload or look out of place, which instantly signals to users and security folks alike that something’s off.

App permissions can trigger entire side quests of their own. Want to connect to a third-party CRM? You’ll need to specify the right OAuth scopes in the manifest—and document what data is accessed, how it’s used, and what’s surfaced back in Teams. Even a small overstep here, like requesting read/write when you only need read, can mean you end up stuck in a days-long review with the security team. Just because your app works doesn’t mean the admin center will let it through. Every permission gets scrutinized, which slows down rollout if you’re not precise.

Then there’s the unglamorous friction of versioning. Once you’ve started sharing the app, updating it is about more than just pushing new code. Each new build often means tweaking the manifest, updating descriptions, icons, endpoint URLs, and making sure nobody loses data or settings on upgrade. More than once, teams have rolled out an update only to find half the feature set suddenly unreachable—or worse, messages that used to work throwing errors due to mismatched backend URLs. Consistent manifest updates, clear version history, and test deployments to scoped pilot groups help catch these bugs before your wider user base hits them.

The admin experience can be a bigger pain point than any dev task. Confused users flood help desks if the app shows up in unexpected locations or if permissions are denied by default. You see this the most in organizations juggling multiple tenants—maybe you’ve started small in a sandbox tenant, but the real deployment has to cross the chasm to test, prod, and even partner environments. Each jump raises new headaches: duplicate configuration, manually uploading manifests, or tweaking permission sets for different regulatory requirements.

Now, let’s talk about compliance—the kind of thing that doesn’t keep you up at night until it suddenly does. GDPR is more than a scary acronym; it’s a practical checklist if your extension handles personal data for EU users. Data residency comes into focus the second your backend leaves a given region. Then there’s authentication, which means deciding if you want Teams SSO for a quick pass or building a custom OAuth flow to hit legacy services. The SSO route is smoother for users but can quickly expose gaps in legacy integration. Meanwhile, any custom OAuth logic will need rock-solid validation and revocation flows or risk exposing data where it shouldn’t surface. Compliance reviews sometimes spot small config errors—like accepting connections from more than intended—or log files that end up outside prescribed regions.

Best practices, pretty much written in admin scars, come down to a handful of habits. Keep your manifest under source control. Document every change and permission explicitly, however small. Always dry-run updates first with a small group and collect logs to see if anything quietly breaks. Set up monitoring—usage analytics and error alerting—not just for uptime, but to flag permission errors, user drop-offs, and the dreaded “no response” message in chat.

There’s a case worth mentioning. One financial services company rolled out a customer lookup extension. The devs handled all the manifest details, scoped permissions tightly, and staged deployments across test and production. Early feedback flagged confusing icons and a missing error message when data wasn’t found—minor, but they slowed initial adoption until fixed. When the final, polished version went live org-wide, support tickets dropped, teams spent less time swapping between apps, and management pointed to faster customer response as a quiet win. A few teething issues aside, careful rollout planning turned what could have become a support burden into a feature users relied on daily.

Done right, deployment stops being a technical hurdle and becomes a natural bridge—your extension ends up woven into every chat and workflow, quietly saving time and lifting the team. When that workflow change happens across every conversation, you start to see the real power of building for Teams extensibility. It’s a practical upgrade, not a theoretical one, and the benefits show up where the work actually lives. From here, there’s an even bigger shift to think about: how these tools reshape entire workflows and help teams get more from every chat, every day.

Conclusion

It’s easy to scroll past message extensions in Teams and never realize how much they can strip out the friction from daily work. Most people reach for bots or spin up tabs when really, the right extension at the right moment can drop exactly the info you need into the flow of conversation. If your team spends too much time jumping between tools, this isn’t about working harder—it’s about getting Teams to do more of the work for you. Try building a message extension that fits your actual workflow. And if you’ve got ideas or want more Teams automation tips, stick around.

Discussion about this episode

User's avatar