HomeNewsletterCommunityToolsArchiveBlogToday's NewsAboutQuick Links Subscribe free
← Back to Blog
Microsoft 365 Microsoft TeamsAI AgentsTeams SDKMCPMicrosoft 365Entra IDGovernance

Building Agents for Microsoft Teams: SDK, MCP, and What IT Admins Need to Know

IA
Imran Awan
15 July 2026

Microsoft announced native SDK support for Teams agents in July 2026. You can now build agents in TypeScript, C#, or Python that live directly inside Teams — not as bots bolted on from the outside, but as first-class participants in channels and chats, capable of acting on conversations, calling APIs, and handing work off to other agents.

This post covers the architecture, the build workflow, how authentication actually works under the hood, and — critically for anyone managing an enterprise fleet — what IT admins need to audit before any of this goes live.

What a Teams agent actually is

There are two types of agents that can run in Microsoft Teams. Understanding the difference matters before you write a single line of code or approve a single Teams app policy.

Type How it works Governance scope
Declarative agent Configured in JSON — no code. Defines scope, instructions, and data connectors. Runs on Copilot's inference engine. Copilot Studio / M365 admin centre
SDK agent (custom) Built with Teams SDK in TypeScript, C#, or Python. Full control over logic, auth, tool calls, and agent-to-agent routing. Teams Admin Centre — app policies, bot permissions

SDK agents have two interaction modes: private (the agent talks directly with one user in a 1:1 chat — like a DM with a bot) and public (the agent is installed into a team or channel and can read messages it is mentioned in). The distinction matters for data access — a channel-installed agent can potentially see far more conversation history than a 1:1 agent.

Scaffolding your first agent

Microsoft ships a CLI to generate the project structure. Install it globally and scaffold a new project:

npm install -g @microsoft/teams.cli

teams project new typescript my-agent

The scaffold creates the directory structure, a TypeScript config, and a starter manifest.json for Teams app registration. You get a working echo agent out of the box — it replies to messages it is mentioned in.

The SDK handles three things you would otherwise build yourself:

SDK responsibility What it replaces
Activity routing Manual webhook parsing and activity type dispatch
Token management Bot Framework credential refresh and JWT validation
Adaptive Card rendering Raw JSON card authoring and action handling

The app manifest — what IT admins actually care about

Every Teams agent ships with an appPackage/manifest.json. This file declares what the agent is allowed to do. Here is a minimal example with the fields your governance review should focus on:

{
  "manifestVersion": "1.17",
  "id": "your-app-guid",
  "name": { "short": "My Agent" },
  "bots": [
    {
      "botId": "your-bot-app-registration-id",
      "scopes": ["personal", "team"],
      "isNotificationOnly": false
    }
  ],
  "permissions": ["identity", "messageTeamMembers"],
  "validDomains": ["your-backend.azurewebsites.net"]
}
Governance flag: The scopes field controls where the agent can be installed. "team" scope means it can be added to any channel in the tenant — not just the team it was built for. Lock this down in Teams Admin Centre app policies before approving the app for org-wide distribution.

Authentication — two layers, not one

Teams agent authentication has two distinct layers. Most developers focus on the second one and get confused when the first one blocks them.

Layer 1 — Bot Channel Service (JWT): Every inbound activity from Teams is signed with a JWT from the Bot Framework. The SDK validates this automatically. If you are self-hosting the agent backend (not on Azure Bot Service), you must validate the JWT yourself or use the SDK's built-in middleware. Skip this and any caller can POST fake activities to your endpoint.

Layer 2 — Entra ID app registration: This is the Entra app that backs the bot registration. It governs what the agent can call via Microsoft Graph. The permissions granted here are what allow the agent to read calendar events, send emails, query users, or access SharePoint. This is the layer IT admins must review and approve in the Entra admin centre.

Entra Admin Centre
Identity Applications App registrations [Your bot app] API permissions Grant admin consent
✓ Admin consent granted for [your tenant] — 15 July 2026
Critical distinction — delegated vs application permissions: Delegated permissions mean the agent acts as the signed-in user — it can only access what that user can access. Application permissions mean the agent acts as itself with tenant-wide access. A Graph permission like Mail.Read as an application permission means the agent can read every mailbox in the tenant. Never approve application permissions without understanding their full blast radius.

Registering MCP tools

The Teams SDK supports MCP (Model Context Protocol) tool registration. This is how you give the agent the ability to call external APIs — your internal ITSM system, a product database, a ticketing tool — without hard-coding the calls into the agent logic.

Here is how tool registration looks in TypeScript:

import { app, McpServer } from '@microsoft/teams.apps';

const mcpServer = new McpServer({ name: 'my-tools', version: '1.0.0' });

mcpServer.tool(
  'get-ticket',
  'Retrieve a support ticket by ID from the ITSM system',
  { ticketId: { type: 'string', description: 'The ITSM ticket ID' } },
  async ({ ticketId }) => {
    const ticket = await itsmClient.getTicket(ticketId);
    return { content: [{ type: 'text', text: JSON.stringify(ticket) }] };
  }
);

app.use(mcpServer);

From the agent's perspective, registered tools are callable capabilities the model can decide to invoke. The SDK handles the tool-call loop — the model responds with a tool call, the SDK executes the registered handler, and the result goes back into the model context.

Agent-to-agent communication — and why IT admins need to care

The Teams SDK supports routing conversations from one agent to another. A triage agent can hand off to a specialist agent. This sounds useful — and it is — but it creates a governance gap that is easy to miss.

The permission inheritance problem: When Agent A hands off to Agent B, Agent B executes with whatever Graph permissions its own Entra app registration holds — not Agent A's. But if Agent B was approved for internal use only and Agent A can be triggered by any Teams user, you have effectively given every Teams user access to Agent B's capabilities. This is not a bug — it is the expected behaviour. But it must be audited explicitly.

IT admin governance checklist

Before any Teams SDK agent goes live in production, run through these four checks:

Teams Agent Governance Checklist
1.Review the Entra app registration permissions. Check every Graph permission — is it delegated or application? Is the scope the minimum needed? Who granted admin consent and when?
2.Check the manifest scopes. Does the agent need team scope or is personal sufficient? Restrict to the minimum scope in Teams Admin Centre app setup policies.
3.Map agent-to-agent routes. Ask the developer: which agents can this agent hand off to? Review the downstream agents' permissions too — not just the entry-point agent.
4.Set app availability policy. In Teams Admin Centre, set the agent to "Specific users" until it has been reviewed. Only move to org-wide after sign-off from your security team.
Teams governance is admin-centre-only: Unlike Intune policies, you cannot manage Teams app permissions via GPO or CSP. All Teams agent governance — app setup policies, permission policies, app availability — is managed exclusively in the Teams Admin Centre.

Finding Teams bot app registrations with PowerShell

If you want an inventory of all Teams bot app registrations in your tenant before agents start proliferating, this Graph query will give you a starting point:

Connect-MgGraph -Scopes "Application.Read.All"

# Find all app registrations that have bot tags
$apps = Get-MgApplication -All | Where-Object {
    $_.Tags -contains "HideApp" -or
    $_.RequiredResourceAccess.Count -gt 0
}

# Filter for those with Bot Framework service access
$botApps = $apps | Where-Object {
    $_.RequiredResourceAccess | Where-Object {
        # Bot Framework service resource ID
        $_.ResourceAppId -eq "bf4a9c9e-3592-4f13-8428-a5c7a3a59e6b"
    }
}

$botApps | Select-Object DisplayName, AppId, CreatedDateTime |
    Export-Csv -Path ".\TeamsBotApps.csv" -NoTypeInformation

Write-Host "$($botApps.Count) Teams bot app registrations found"

Cross-reference the output against your approved app list in Teams Admin Centre. Any app registration that appears here but is not in your approved app policy is a potential governance gap.

admin.teams.microsoft.com
Teams Admin Centre › Teams apps › Manage apps
My Agent
Custom app · Bot · SDK · v1.0.0
Pending review
Triage Agent
Custom app · Bot · Declarative · v2.1.0
Allowed
App availability: Specific users and groups · Set under Setup policies before org-wide approval

References

Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

Microsoft 365
Copilot in Excel for Finance: Skills, Data Connectors, and Plan…
Microsoft has rebuilt Copilot in Excel around how finance teams actually work — with…
Microsoft 365
Microsoft 365 Copilot Auto-Install Block Guide — IT Admin…
Microsoft is pushing the M365 Copilot app to all enterprise Windows devices June 15–July…
Microsoft 365
Agent 365 Now Requires M365 E5 — Licensing Impact and Your…
From June 1 2026, new Agent 365 purchases require M365 E5. Existing customers are…