Generated banner for Teams App Developer
Generated logo for Teams App Developer

Teams App Developer

MicrosoftOfficialPublished by Microsoft

  • Skill
  • Tool integration
  • Software development
  • MIT
  • Medium risk

From the author

Builds, tests, and deploys Microsoft 365 apps and agents for Teams and Copilot. Includes sub-skills for project creation, local testing, cloud deployment, troubleshooting, and Slack-to-Teams migration. USE FOR: Teams agent, bot, tab, message extension, Declarative Agents, Custom Engine Agents, local testing, Agents Playground, Azure resource provision, remote deployment, Slack to Teams migration, cross-platform bot development, Block Kit to Adaptive Cards conversion. DO NOT USE FOR: general web development, non-bot/non-Teams projects.
— the description by Microsoft

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The teams-app-developer skill provides a structured framework for managing the lifecycle of Microsoft 365 agents and Teams applications. It leverages the ATK CLI to handle project scaffolding, local testing via the Agents Playground, cloud provisioning on Azure, and troubleshooting. The skill includes specialized guidance for migrating Slack bots to Teams, including converting Block Kit UI to Adaptive Cards, and provides access to an extensive library of micro-expert documentation for cross-platform development.

What it does

  • Scaffolds new Microsoft 365 agents and Teams applications from templates.
  • Facilitates local testing using the Agents Playground or Teams-specific environments.
  • Automates Azure resource provisioning and cloud deployment workflows.
  • Provides diagnostic procedures for common authentication and configuration errors.
  • Supports migration of Slack bots to the Teams platform.
  • Manages project configuration and environment variables for ATK-based projects.

When to use it

  • When starting a new Teams app, bot, or Declarative Agent project.
  • When you need to test an agent locally before deploying to the cloud.
  • When migrating existing Slack bots to the Microsoft Teams ecosystem.
  • When troubleshooting deployment or authentication issues in a Teams project.
  • When you need to provision Azure infrastructure for a Teams application.

Advantages

  • Streamlines the development lifecycle with standardized CLI commands.
  • Reduces development time by offering a local testing playground.
  • Provides expert-level guidance for complex cross-platform migrations.
  • Ensures consistent configuration management across development environments.
  • Includes robust error-handling protocols for common platform-specific pitfalls.

Usage examples

“Create a new Teams bot project using the default template.”
The agent will initialize a new project folder, configure the necessary YAML files, and guide you through the initial setup using the ATK CLI.
“How do I migrate my Slack bot to Microsoft Teams?”
The agent will initiate the slack-to-teams workflow, providing access to cross-platform bridging experts and guidance on converting UI components.
“My Teams bot is returning a 401 error, how do I fix it?”
The agent will trigger the troubleshooting workflow, checking your environment variables, tunnel status, and authentication configuration.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/microsoft/teams-app-developer/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip teams-app-developer.zip -d .agents/skills

Documentation by Microsoft

Microsoft 365 Agents Toolkit Skill

Build Microsoft 365 agents and Teams apps using the ATK CLI.

AI Behavior Guidelines

  1. Testing Strategy: Recommend Agents Playground first (faster, no M365 needed). Use Teams workflow only if user explicitly requests it.

  2. Environment Variables: NEVER hardcode secrets or make up placeholder values. Always ask users for real values.

  3. Error Handling: Read error messages carefully. Check env/.env.local, .localConfigs, and atk auth list. Common pitfalls:

    • AADSTS7000229 → aadApp/create missing generateServicePrincipal: true in YAML — add it and re-provision

    • Missing TENANT_ID in .localConfigs → SDK uses wrong token authority → 401 from Bot Connector

    • 401 persists after auth fix → devtunnel URL may be blacklisted — create a fresh tunnel

    • See troubleshoot/troubleshoot.md for full diagnostic steps

  4. Long-Running Commands — WAIT for completion:

    • atk new, atk provision, atk deploy can take several minutes

    • Always wait for completion before running the next step (timeout 120000ms+)

  5. Local Service Startup — Hangs terminal (expected):

    • npm run dev, npm start, python app.py, devtunnel host, etc. will hang — the process keeps running indefinitely

    • ALWAYS run as a background process (isBackground=true) — NEVER use isBackground=false for these commands

    • Do NOT wait for it to "finish" — verify startup by checking output for "listening on port" or tunnel URL

    • If errors appear, read logs, diagnose, fix, restart

    • Use a NEW terminal to launch Agents Playground or open Teams sideloading URL

  6. Monitor App Logs: Periodically check background terminal output for runtime errors. If the app crashes, read the error, fix the root cause, and restart.

  7. Telemetry Tagging: Before running any atk CLI commands, set the session environment variable so all CLI invocations are tagged as skill-initiated:

    export ATK_CLI_SKILL=true

    Run this once at the start of the session. All subsequent atk commands in the same terminal will inherit it.

ATK CLI Setup

atk --version  # Must be > 1.1.5-beta

If ATK is not found or version is too old:

npm i -g @microsoft/m365agentstoolkit-cli@beta

CLI Global Options

OptionMeaningRecommendation
-iInteractive modeAlways use -i false in automation to avoid hanging
-fProject folderDefault to be current directory, used when specifying a custom folder. When scaffolding a new project, this is the parent folder where the project folder will be created under.
-hCommand helpUse atk <command> -h for quick syntax checks

Sub-Skills

Sub-SkillWhen to UseReference
create-projectScaffold new project from template, choose template, atk newcreate-project/create-project.md
test-playgroundTest locally with Agents Playground, agentsplayground, quick testingtest-playground/test-playground.md
test-teamsRun on Teams, devtunnel, sideload, Teams testing, test in Copilottest-teams/test-teams.md
provision-deployProvision Azure resources, deploy to cloud, atk provision, atk deployprovision-deploy/provision-deploy.md
troubleshootFix errors, 401, port conflicts, YAML errors, stale botstroubleshoot/troubleshoot.md
slack-to-teamsMigrate Slack bot to Teams, cross-platform bridging, Block Kit to Adaptive Cardsslack-to-teams/SKILL.md

MANDATORY: Before executing any workflow, read the corresponding sub-skill document.

Shared References

  • manifest-and-yaml.md — Project files, YAML config, env vars, .localConfigs flow

  • commands.md — ATK CLI commands: package, validate, share, collaborate

  • templates.md — Complete template catalog with language support

  • experts/ — 100+ micro-expert files: Teams SDK, Slack SDK, cross-platform bridging, deploy, AI models, security, language conversion

  • docs/ — Platform comparison guides: UI, messaging, identity, infrastructure, feature gaps

Workflow Chains

Match user intent to the smallest valid workflow.

User IntentWorkflow (read in order)
Build new app from scratchcreate-project → test-playground
Test existing project locallytest-playground (recommended) or test-teams
Deploy to Azureprovision-deploy
Fix broken bottroubleshoot → re-test
Migrate Slack bot to Teamsslack-to-teams

MANDATORY: Before executing any slack-to-teams workflow, read slack-to-teams/SKILL.md first. The sub-skill contains a routed expert system with 100+ micro-expert files for cross-platform bot development.

ATK Project Context Resolution

Resolve config values only when missing. If a value is already known in the session, reuse it.

Step 1: Detect ATK Project

If m365agentstoolkit*.yml exists in the current folder, treat it as an ATK project and parse configuration.

Step 2: Resolve Common Configuration

Resolve variables referenced in m365agentstoolkit*.yml. Common variables: AZURE_OPENAI_API_KEY AZURE_OPENAI_ENDPOINT AZURE_OPENAI_DEPLOYMENT_NAME

Step 3: Collect Missing Values

If required values are missing, ask the user for only the missing ones.

Refer to manifest-and-yaml.md for full config-file details.

Files

experts/bridge/identity-oauth-bridge-ts.md

identity-oauth-bridge-ts

purpose

Bridges Slack and Teams/Azure AD identity systems (user/channel IDs, OAuth, signing) for cross-platform bots targeting Slack, Teams, or both.

rules

  1. Slack uses proprietary ID formats: user IDs start with U (e.g., U01ABCDEF), channel IDs start with C (e.g., C02GHIJKL), team/workspace IDs start with T (e.g., T03MNOPQR), and bot IDs start with B. These IDs have no relationship to Teams/Azure AD identifiers and cannot be mapped automatically. api.slack.com/types

  2. Teams identifies users by Azure AD Object ID (a GUID like 00000000-0000-0000-0000-000000000000), available at activity.from.aadObjectId. Conversation IDs are opaque strings like 19:[email protected] for channels or a]concat@... for personal chats. These formats are fundamentally different from Slack IDs. learn.microsoft.com -- Activity schema

  3. Slack's request verification via signingSecret (HMAC-SHA256 of request body) is replaced by Bot Framework JWT token validation in Teams. The Teams SDK handles JWT validation automatically -- no manual signing secret check is needed. learn.microsoft.com -- Bot authentication

  4. Slack's bot token (xoxb-...) used for API calls is replaced by Azure Bot credentials (CLIENT_ID + CLIENT_SECRET + TENANT_ID). The Teams SDK uses these to obtain tokens for the Bot Framework service automatically. learn.microsoft.com -- Register a bot

  5. Slack OAuth scopes (e.g., chat:write, users:read, commands) map to Azure AD permissions for the Microsoft Graph API (e.g., User.Read, ChannelMessage.Send). Slack scopes are configured in the Slack app dashboard; Azure AD permissions are configured in the Azure Portal under App Registration > API Permissions. learn.microsoft.com -- Graph permissions

  6. Slack user tokens (obtained via OAuth users:read or user token grant) map to Teams SSO / OAuth card flow. In Teams, configure an OAuth connection in the Azure Bot resource, then use isSignedIn / signin() / userGraph in handlers to access the user's delegated token for Graph API calls. learn.microsoft.com -- Bot SSO

  7. To resolve user identity across platforms during migration, use a shared attribute like email address. Query Slack's users.info API for the user's email, then look up the same email in Azure AD via Microsoft Graph users?$filter=mail eq '...'. Build a mapping table of Slack user ID to AAD Object ID. learn.microsoft.com -- Graph users API

  8. Any data stored with Slack IDs as keys (user preferences, conversation history, permissions) must be re-keyed to Teams/AAD IDs. Plan a data migration step that uses the email-based mapping table to translate stored Slack user IDs to AAD Object IDs. learn.microsoft.com -- Migration planning

  9. Slack workspace-level operations (e.g., listing all users via users.list, posting to any channel) require bot scopes. In Teams, equivalent operations use Microsoft Graph with application permissions (consented by a tenant admin). Use appGraph for service-to-service calls and userGraph for delegated user calls. learn.microsoft.com -- Graph auth overview

  10. Teams supports managed identity as an alternative to client secret for production deployments on Azure. Set managedIdentityClientId: 'system' in App options to use Azure Managed Identity instead of storing secrets in environment variables. learn.microsoft.com -- Managed identity

patterns

Environment variable mapping between Slack and Teams

Slack .env:

# Slack Bot Configuration
SLACK_BOT_TOKEN=your-slack-bot-token
SLACK_SIGNING_SECRET=your-signing-secret
SLACK_APP_TOKEN=your-slack-app-token
SLACK_CLIENT_ID=your-slack-client-id
SLACK_CLIENT_SECRET=your-slack-client-secret
PORT=3000

Teams .env:

# Azure Bot Registration
CLIENT_ID=00000000-0000-0000-0000-000000000000
CLIENT_SECRET=your-azure-bot-client-secret
TENANT_ID=00000000-0000-0000-0000-000000000000
PORT=3978

Environment variable mapping table:

Slack VariableTeams VariableNotes
SLACK_BOT_TOKEN (xoxb-...)CLIENT_ID + CLIENT_SECRETTeams SDK manages token acquisition automatically
SLACK_SIGNING_SECRET(not needed)Bot Framework JWT validation is automatic
SLACK_APP_TOKEN (xapp-...)(not needed)Socket mode is Slack-only; Teams uses HTTPS
SLACK_CLIENT_IDCLIENT_IDAzure Bot App Registration ID (GUID)
SLACK_CLIENT_SECRETCLIENT_SECRETAzure Bot App Registration secret
(not applicable)TENANT_IDAzure AD tenant ID (new for Teams)
PORT (default 3000)PORT (default 3978)Different conventional defaults

Identity concept mapping table:

Slack ConceptTeams/Azure AD ConceptFormat
User ID (U01ABCDEF)AAD Object IDGUID (00000000-...)
Channel ID (C02GHIJKL)Conversation ID19:[email protected]
Team/Workspace ID (T03MNOPQR)Tenant IDGUID
Bot ID (B04STUVWX)Bot ID (from App Registration)GUID
DM Channel ID (D05YZABCD)Personal conversation IDOpaque string
Signing SecretBot Framework JWTAutomatic validation
Bot Token (xoxb-...)Client credentials flowCLIENT_ID + CLIENT_SECRET
User Token (xoxp-...)Delegated OAuth tokenSSO / OAuth card flow
OAuth scopes (chat:write)Azure AD permissions (ChannelMessage.Send)Configured in Azure Portal
Slack App DashboardAzure Portal + manifest.jsonConfig split between portal and file
Migrating authentication from Slack OAuth to Teams SSO

Slack (before) -- Using Slack OAuth for user identity:

import { App } from "@slack/bolt";

const app = new App({
  token: process.env.SLACK_BOT_TOKEN!,
  signingSecret: process.env.SLACK_SIGNING_SECRET!,
});

app.command("/whoami", async ({ ack, command, client }) => {
  await ack();
  // Use the bot token to look up user info
  const userInfo = await client.users.info({ user: command.user_id });
  const email = userInfo.user?.profile?.email ?? "unknown";
  const name = userInfo.user?.real_name ?? "unknown";
  await client.chat.postMessage({
    channel: command.channel_id,
    text: `You are ${name} (${email})`,
  });
});

Teams (after) -- Using Teams SSO and Microsoft Graph:

import { App } from "@microsoft/teams.apps";
import { ConsoleLogger } from "@microsoft/teams.common";
import { DevtoolsPlugin } from "@microsoft/teams.dev";
import * as endpoints from "@microsoft/teams.graph-endpoints";

const app = new App({
  clientId: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
  tenantId: process.env.TENANT_ID,
  logger: new ConsoleLogger("my-bot", { level: "info" }),
  plugins: [new DevtoolsPlugin()],
  oauth: { defaultConnectionName: "graph" },
});

app.message(/^\/?whoami$/i, async ({ isSignedIn, signin, userGraph, send }) => {
  // If user is not signed in, trigger the SSO/OAuth flow
  if (!isSignedIn) {
    await signin({ signInButtonText: "Sign In to continue" });
    return;
  }

  // Use the delegated Graph client to get user profile
  const me = await userGraph.call(endpoints.me.get);
  await send(`You are ${me.displayName} (${me.mail})`);
});

// Handle successful sign-in
app.event("signin", async ({ send, userGraph }) => {
  const me = await userGraph.call(endpoints.me.get);
  await send(`Welcome, ${me.displayName}! You are now signed in.`);
});

app.start(3978);
Building a Slack-to-AAD user ID mapping table
import { WebClient } from "@slack/web-api";
import { Client as GraphClient } from "@microsoft/microsoft-graph-client";

interface UserMapping {
  slackUserId: string;
  slackEmail: string;
  aadObjectId: string | null;
  aadDisplayName: string | null;
}

async function buildUserMappingTable(
  slackClient: WebClient,
  graphClient: GraphClient
): Promise<UserMapping[]> {
  const mappings: UserMapping[] = [];

  // Step 1: Fetch all Slack users
  const slackUsers = await slackClient.users.list({});
  const members = slackUsers.members ?? [];

  for (const slackUser of members) {
    if (slackUser.deleted || slackUser.is_bot) continue;

    const email = slackUser.profile?.email;
    if (!email) {
      mappings.push({
        slackUserId: slackUser.id!,
        slackEmail: "",
        aadObjectId: null,
        aadDisplayName: null,
      });
      continue;
    }

    // Step 2: Look up the same email in Azure AD via Graph
    try {
      const result = await graphClient
        .api("/users")
        .filter(`mail eq '${email}' or userPrincipalName eq '${email}'`)
        .select("id,displayName,mail")
        .get();

      const aadUser = result.value?.[0];
      mappings.push({
        slackUserId: slackUser.id!,
        slackEmail: email,
        aadObjectId: aadUser?.id ?? null,
        aadDisplayName: aadUser?.displayName ?? null,
      });
    } catch {
      mappings.push({
        slackUserId: slackUser.id!,
        slackEmail: email,
        aadObjectId: null,
        aadDisplayName: null,
      });
    }
  }

  return mappings;
}

// Step 3: Use the mapping to re-key stored data
async function migrateUserData(
  mappings: UserMapping[],
  oldStore: Map<string, unknown>,
  newStore: Map<string, unknown>
): Promise<void> {
  for (const mapping of mappings) {
    if (!mapping.aadObjectId) continue;
    const data = oldStore.get(mapping.slackUserId);
    if (data) {
      newStore.set(mapping.aadObjectId, data);
    }
  }
}
Converting Slack OAuth implementation code to Teams OAuth

Slack SDKs (especially java-slack-sdk and @slack/bolt) implement OAuth with explicit services: InstallationService for storing tokens, OAuthStateService for CSRF, and OAuthCallbackHandler for the redirect. Teams replaces ALL of this with declarative config.

Slack Java SDK OAuth (before):

// --- Slack Java SDK OAuth implementation ---
// InstallationService — stores bot tokens per workspace
public class FileInstallationService implements InstallationService {
    public void saveInstallerAndBot(Installer installer) { /* persist to DB */ }
    public Installer findInstaller(String enterpriseId, String teamId) { /* lookup */ }
    public Bot findBot(String enterpriseId, String teamId) { /* lookup */ }
    public void deleteBot(Bot bot) { /* remove */ }
    public void deleteInstaller(Installer installer) { /* remove */ }
}

// OAuthStateService — generates and validates CSRF state parameter
public class FileOAuthStateService implements OAuthStateService {
    public String issueNewState(Request req) { /* generate random state */ }
    public boolean isValid(OAuthState state) { /* validate state */ }
    public void consume(OAuthState state) { /* mark used */ }
}

// App configuration with OAuth
App app = new App(AppConfig.builder()
    .clientId(System.getenv("SLACK_CLIENT_ID"))
    .clientSecret(System.getenv("SLACK_CLIENT_SECRET"))
    .signingSecret(System.getenv("SLACK_SIGNING_SECRET"))
    .oAuthInstallPath("/slack/install")
    .oAuthRedirectUriPath("/slack/oauth_redirect")
    .oAuthCompletionUrl("https://example.com/success")
    .oAuthCancellationUrl("https://example.com/cancel")
    .installationService(new FileInstallationService())
    .oauthStateService(new FileOAuthStateService())
    .build());

Teams OAuth (after):

// --- Teams OAuth — all of the above is replaced by config ---
import { App } from '@microsoft/teams.apps';
import { ConsoleLogger } from '@microsoft/teams.common';

const app = new App({
  clientId: process.env.CLIENT_ID,
  clientSecret: process.env.CLIENT_SECRET,
  tenantId: process.env.TENANT_ID,
  logger: new ConsoleLogger('my-bot', { level: 'info' }),

  // This single config block replaces:
  // - InstallationService (token storage is managed by Azure Bot Service)
  // - OAuthStateService (CSRF handled by Bot Framework)
  // - OAuthCallbackHandler (redirect handled by Azure Bot Service)
  // - Token refresh logic (managed by Azure Bot Service)
  oauth: {
    defaultConnectionName: 'graph', // configured in Azure Portal
    // That's it. No custom services needed.
  },
});

// Instead of Slack's multi-step OAuth flow with custom storage:
// 1. Azure Bot Service manages token acquisition, refresh, and storage
// 2. CSRF protection is built into the Bot Framework sign-in flow
// 3. The OAuth connection is configured in Azure Portal (not code)
// 4. Use isSignedIn/signin() in handlers to trigger auth when needed

app.message(/^profile$/i, async ({ isSignedIn, signin, userGraph, send }) => {
  if (!isSignedIn) {
    await signin();
    return;
  }
  const me = await userGraph.call(endpoints.me.get);
  await send(`Signed in as ${me.displayName}`);
});

What gets DELETED during conversion:

Slack OAuth ComponentTeams EquivalentAction
InstallationService + DB storageAzure Bot Service token cacheDelete entirely
OAuthStateService + CSRF tokensBot Framework built-in CSRFDelete entirely
OAuthCallbackHandler + redirect routesAzure Bot Service callbacksDelete entirely
Token refresh / expiry logicAzure Bot Service auto-refreshDelete entirely
/slack/install routeTeams app install flowDelete entirely
/slack/oauth_redirect routeAzure Bot ServiceDelete entirely
Multi-workspace token lookupManaged identity / tenant configDelete entirely
Slack OAuth scopes in codeAzure Portal API PermissionsConfigure in portal
Reverse direction (Teams → Slack)

For Teams → Slack, the same mapping table applies in reverse. AAD Object IDs need mapping to Slack user IDs via email lookup. Key reverse mappings:

  • activity.from.aadObjectId (GUID) → Slack User ID (U...) via email-based lookup: query Graph users/{aadObjectId} for email, then users.lookupByEmail in Slack

  • activity.conversation.id (19:[email protected]) → Slack Channel ID (C...) via channel name mapping or a stored lookup table

  • CLIENT_ID + CLIENT_SECRET + TENANT_ID → SLACK_BOT_TOKEN (xoxb-...) + SLACK_SIGNING_SECRET

  • Azure AD permissions (ChannelMessage.Send, User.Read) → Slack OAuth scopes (chat:write, users:read)

  • Teams SSO / OAuth card flow → Slack OAuth with InstallationService and OAuthStateService (Slack requires explicit token storage and refresh logic that Azure Bot Service handles automatically)

  • Bot Framework JWT validation (automatic) → Slack signing secret HMAC-SHA256 verification (must add signingSecret to Bolt config)

  • Azure Managed Identity → no Slack equivalent; use environment variables or secret manager for Slack tokens

  • The email-based user mapping table built for Slack → Teams works identically in reverse

pitfalls

  • Assuming Slack IDs can be reused: Slack IDs (U..., C..., T...) are completely incompatible with Teams/AAD IDs. Any code that stores or references Slack IDs must be updated to use AAD Object IDs and conversation IDs.

  • Manual signing secret validation: Developers sometimes port Slack's HMAC verification middleware to Teams. This is unnecessary -- the Bot Framework validates JWT tokens automatically. Remove all signing secret verification code.

  • Expecting ephemeral identity context: Slack's user_id is always present in command and action payloads. In Teams, activity.from.aadObjectId may be undefined in some contexts (e.g., webhook-originated activities). Always null-check.

  • OAuth scope confusion: Slack scopes like chat:write do not map 1:1 to Azure AD permissions. Audit each Slack scope used and find the equivalent Graph permission. Some Slack capabilities require multiple Graph permissions or a different API approach entirely.

  • Storing tokens insecurely: Slack bot tokens are long-lived strings. Azure Bot credentials use short-lived JWT tokens managed by the SDK. Never try to cache or store Bot Framework tokens manually.

  • Skipping the user mapping step: Without building a Slack-to-AAD mapping table, any user-specific data (preferences, history, permissions) stored under Slack IDs becomes inaccessible. Plan this migration step early.

  • Tenant ID confusion: Slack workspaces have a single team ID. Azure AD tenants can contain multiple Teams organizations. Ensure TENANT_ID is set correctly -- use the specific tenant ID for single-tenant apps or common for multi-tenant.

  • Forgetting to configure OAuth connection: Teams SSO requires an OAuth connection configured in the Azure Bot resource (Settings > OAuth Connection Settings). Without it, signin() calls fail silently.

  • Porting OAuth implementation code instead of deleting it: Slack's InstallationService, OAuthStateService, and OAuthCallbackHandler have NO Teams equivalent. Azure Bot Service handles token storage, CSRF, and callbacks automatically. Attempting to port these services wastes effort and introduces bugs. Delete them entirely and use the oauth: { defaultConnectionName } config.

  • Custom token refresh logic: Slack apps often implement manual token refresh with oauth.v2.access. Azure Bot Service refreshes tokens automatically. Delete all refresh code.

references

instructions

This expert covers bridging Slack and Teams/Azure AD identity and authentication systems. Use it when adding cross-platform support in either direction: understanding the differences between Slack IDs (U/C/T/B prefixed) and Teams IDs (AAD Object IDs, conversation IDs); bridging signing/verification (Slack signing secret ↔ Bot Framework JWT); mapping environment variables (SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET ↔ CLIENT_ID, CLIENT_SECRET, TENANT_ID); converting between Slack OAuth and Teams SSO with Microsoft Graph; building a bidirectional user mapping table using email as the shared attribute; bridging Slack OAuth scopes and Azure AD permissions; and configuring authentication for either platform. Pair with ../teams/auth.oauth-sso-ts.md for Teams OAuth/SSO flow, and ../teams/graph.usergraph-appgraph-ts.md for Graph API user lookup during identity mapping.

research

Deep Research prompt:

"Write a micro expert for bridging Slack and Teams/Azure AD identity systems bidirectionally. Cover Slack ID formats (U/C/T/B IDs) vs Teams IDs (AAD Object IDs, conversation IDs), signing/verification bridging (signing secret <-> Bot Framework JWT), environment variable mapping in both directions, Slack OAuth <-> Teams SSO flow, Slack scopes <-> Azure AD Graph permissions, building a bidirectional user mapping table via email lookup, data re-keying strategies, and managed identity for production. Include mapping tables and TypeScript examples."

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an API key, Needs Python, Needs Node.js

Security

What our scanner noticed· Medium risk

  • Possible data-exfiltration endpoints
  • Instructions that use the network
  • Downloads piped into a shell

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
Microsoft
Publisher
Microsoft (Official)
Source
microsoft/skills · .github/plugins/microsoft-365-agents-toolkit/skills/teams-app-developer · commit 0696600
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Microsoft.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download teams-app-developer.zip