Yes, I know what you're thinking! Another day, another product. As a consultant with limited time and resources, I really must pick and choose my battles. After all, what I choose to do also decides what I won't be able to do. In that vein, I think that Microsoft Teams, the newest collaboration product in Office 365, deserves a look.

Microsoft Teams deserves a look for both business users and developers. I'll keep this article focused on developers.

What is Microsoft Teams?

At a fundamental level, Microsoft Teams is a collaboration product. It's integrated into Office 365, but it's a new product built from the ground up. It can be used in a browser, on your phone, or as a desktop application. If you were wondering, yes, it's internally built using Web-based technologies such as Electron, Cordova or similar, and the usual Web stack, such as HTML, JavaScript, etc.

What's compelling about Teams is that it feels like a modern product. It doesn't feel like a dowdy old product rooted in 2001 that doesn't scale to modern organization needs or work properly - or not at all - on a Mac. It's ready for today's information worker! Ugh, did I just use that term again, “information worker?” Let's get back to the developer story.

The Developer Story for Teams

One way to think of teams is chatrooms. It's more than that, of course, but at a very high level, you create channels (a.k.a chatrooms) within your organization where people can communicate with each other. Users can also engage in a 1:1 conversation, upload files to share with their team, or have applications push in information in numerous forms.

And that's where you come in! You're the developer, and you can extend teams in the following ways:

  • Tabs: Provides a dedicated canvas that lets team members access your service while connected to a channel or private chat.
  • Bots: Built on the Microsoft Bot Framework, allows team members to interact with your service via conversations.
  • Connectors: Allow your services to send notifications into channels. These notifications can include rich actionable messages that can expose some user interface, allowing users to interact directly with your service through a channel. I covered this in the May/June 2017 issue of CODE Magazine (
  • Extensions: Allow you to share your app's content directly into team conversations.
  • Sending messages: Permits contact directly into a user's activity feed.


Tabs allow you to embed Web pages inside a team. From a user point of view, this is extremely simple to do. Just visit any team channel, and choose to click on the + button, as shown in Figure 1.

Figure 1: Adding a tab
Figure 1: Adding a tab

Clicking on the Add button brings up a dialog box, as shown in Figure 2, that allows you to embed any relevant content right inside a team.

Figure 2: Tabs available out of the box
Figure 2: Tabs available out of the box

Go ahead and try embedding any tab inside your channel. These are just Web pages. You can create a simple website with anything you wish in it. It could be dashboards, detail pages; really, just about anything. And you register it using a simple manifest file. When you create this website that works as a tab, you have a choice of implementing one or two pages.

  • The configuration page: This is optional. Configurable tabs give you the opportunity to allow the user to specify some configuration information before the tab is added. You can also allow users to update a tab after they add it via this page.
  • The content page: This page is where the functionality of your tab lives; it's the page the user sees when the user visits the tab via a team.

You can also add tabs in one of two scopes. One way is in the team scope where you add tabs to a channel. These are currently configurable tabs only. The other way is that you can add them in personal scope, where the user interacts with the tab via the app bar. Currently, only static tabs are allowed in the personal scope.

Additionally, your website that works as a tab, i.e., the content page, must follow the following rules:

  • It must be hosted on https
  • The content must work in an iframe, and you must set the following HTTP header:
* *
  • For IE11, you also need to set the X-Content-Security-Policy header.
  • Once your page loads, you need to call the JavaScript method microsoftTeams.initialize() to show your page.
  • You also need a manifest file, and all URLs being used within your tab must be under the “validDomains” list in your manifest. You may reference the schema for the teams manifest file here

As I mentioned earlier, your tab can have a configuration page specified as the “configurationUrl” parameter of the manifest file. There are some requirements for this configuration page also.

  • The Save button on this page is disabled by default. The idea is that when the user has finished configuring the tab, the Save button becomes enabled. You can enable the Save button at the right moment by calling the microsoftTeams.settings.setValidityState(true) method.
  • This configuration page is responsible for letting the content page know what settings it needs to run under. You can do so by calling the microsoftTeams.settings.setSettings method.
  • You also have the opportunity to fire off a long-running operation when the user hits Save. You can register the event handler by calling the microsoftTeams.settings.registerOnSaveHandler method and passing in a function. The only requirement here is that you must complete this operation in 30 seconds or Microsoft Teams terminates the operation and shows an error message. The Save handler also needs to notify you of success or failure. It can do so by calling saveEvent.notifySuccess() or saveEvent.notifyFailure() methods. The saveEvent parameter is passed in as a parameter to the Save handler.

In either the content page or the configuration page, you can authenticate the user by calling the microsoftTeams.authentication.authenticate method. This may be necessary if the user needs to first authenticate before being able to configure a tab. For instance, you may have bug-tracking software that you wish to add as a tab. This bug-tracking software has its own authentication mechanism. The microsoftTeams.authentication.authenticate method allows you to authenticate at the bug-tracking software's URL. That URL opens in a pop-up window and is able to notify teams of success or failure. Your app can set its session cookie so the user doesn't need to sign in again.

It's perhaps also valuable to understand the context under which your tab is operating. Context contains valuable information such as team ID, channel ID, locale, theme, etc. This context can be easily received in your Web application by calling the microsoftTeams.getContext method. You can also react to theme changes by using a theme handler. This theme handler can be registered using the microsoftTeams.registerOnThemeChangeHandler method.


Next, let's talk about bots. Bots are two-way conversations, except you're talking to a computer program! Really!

It isn't as fancy as it sounds. You simply use the Microsoft Bot Framework to author a bot and register it within your team. Bots currently are supported in 1:1 chats (personal scope) or channel conversations (team scope). Group chats don't currently support bots. Bots appear like any other user except they have a hexagonal avatar icon and no mood message.

Creating a bot for a Microsoft Team takes four main steps:

  1. Register the bot at If you wish to have the bot surface up in Microsoft Teams, you need to add Microsoft Teams as a channel and reuse any Microsoft App ID that you generate on the registration page. You'll need to update your app package/manifest for the bot with this App ID.
  2. You need to write the bot. You can do so using .NET using the Microsoft.Bot.Connector.Teams nuget package, or the botbuilder-teams NPM package, or you can use the bot connector API, which is a bunch of REST APIs allowing you to build the bot in any platform. Imagine that you could write an iOS app where you can say “Hey Siri, ask the Microsoft Bot Framework to do something useful,” and then expose that same bot in a Microsoft Team.
  3. Develop and test the bot using the bot framework emulator.
  4. Deploy the bot to a cloud service. Azure works fine.

Once your bot is written and ready, you need to make it available in teams. You can sideload the bot package and sideload it into a test team for dev purposes. Creating the package involves creating a zip file with:

  • A manifest file called manifest.json describing your bot
  • A transparent outline icon and a full-color icon meeting certain requirements

Once the bot package is created, you simply sideload it in a team. However, for sideloading to work, you need to enable sideloading of apps. To enable side loading of apps:

  1. Sign in as tenant administrator.
  2. Under Admin, go to Settings > Services & Add-ins or Apps
  3. Find Microsoft Teams in that list.
  4. Set the settings as shown in Figure 3.
Figure 3: Allowing sideloading of apps
Figure 3: Allowing sideloading of apps

Once you've enabled sideloading, visit the team you wish to sideload using the View Team menu option, as shown in Figure 4.

Figure 4: The View team option.
Figure 4: The View team option.

Once on the View Team page, choose Sideload a bot or tab option, as shown in Figure 5.

Figure 5: Sideload a bot or tab
Figure 5: Sideload a bot or tab

Choosing to sideload a bot or tab prompts you to upload the zip file containing the packaged bot. Go ahead and upload it. Once the bot is sideloaded, you can use it by @mentioning it. To access it in direct chats, you can access it either via the App home, or @mention it in a channel.

An important thing to remember here is that removing a bot doesn't remove previous conversations. Ideally speaking, you should sideload it into teams as a last step. You can test the bot quite well via the bot-testing framework beforehand.


Connectors allow your custom code to push information into teams. I've previously covered Office 365 connectors in depth in the May/June 2017 issue of CODE Magazine (

Extensions and Sending Messages to the Activity Feed

Extensions allow users to quickly share an app's content directly inside a team conversation. Imagine throwing in a bug report as a chat item. Better yet, imagine being able to resolve the bug right within the context of the team. Or being able to interact with a report. The possibilities are endless. These extensions appear as rich cards within the chat. In fact, when you're typing in the chat box, there are some extensions already there at the bottom of the chat window, as can be seen in Figure 6.

Figure 6: Existing extensions
Figure 6: Existing extensions

Adding a custom extension is a matter of authoring a cloud-hosted service that listens to user requests and responds with structured data, such as cards. You can integrate the service with teams via the Bot Framework activity objects. The process of adding an extension is quite simple

Sending messages to the activity feed leverages the Bot Framework. You can flag specific messages so they appear in the user's activity feed as notifications. All you have to do is mark your bot message with the following snippet:

"channelData": {
    "notification": {
        "alert": true

Note that both extensions and sending messages to the user's activity feed are currently in preview.


SharePoint, the original collaboration tool, is often mistaken as the only collaboration tool Microsoft offers, perhaps because of its widespread use and success. But let's be honest, the dev story of SharePoint has always been clunky. The platform itself is heavy and mired in decisions taken in 2001 or before. I have no doubt that SharePoint will continue to survive and improve, but improve it must.

Meanwhile, we have Microsoft Teams. It's not a replacement for SharePoint, but think of it like a persistent chatroom that's secure, extensible, compelling, and cross-platform. Extensible is where you, the developer, come in. The possibilities are endless, and I hope to explore them further in future articles.

Until then, be amazing and write some code!