Claude
Skills
Sign in
Back

teams-api

Included with Lifetime
$97 forever

Microsoft Teams automation using Graph API, Bot Framework, Adaptive Cards, and webhooks for enterprise messaging and collaboration

communicationteamsmicrosoftgraph-apibotadaptive-cardsenterprisemessagingazure

What this skill does


# Microsoft Teams API Skill

Master Microsoft Teams automation using the Microsoft Graph API and Bot Framework. This skill covers channel messaging, adaptive cards, bot development, webhooks, and enterprise integration patterns for Microsoft 365 environments.

## When to Use This Skill

### USE when:
- Building bots for Microsoft 365 organizations
- Creating enterprise notification systems
- Integrating with Azure DevOps and Microsoft ecosystem
- Building approval workflows in Teams
- Automating meeting scheduling and management
- Creating messaging extensions for Teams apps
- Implementing compliance-aware messaging solutions
- Building internal tools with Adaptive Cards

### DON'T USE when:
- Organization uses Slack primarily (use slack-api)
- Need simple webhooks only (use incoming webhooks directly)
- No Microsoft 365 subscription available
- Building consumer-facing chat applications
- Need real-time gaming or high-frequency updates

## Prerequisites

### Azure App Registration

```bash
# 1. Go to Azure Portal -> Azure Active Directory -> App registrations
# 2. New registration:
#    - Name: "Teams Bot App"
#    - Supported account types: Accounts in this organizational directory
#    - Redirect URI: Web - https://your-app.azurewebsites.net/auth

# Required API Permissions (Microsoft Graph):
# Application permissions:
# - ChannelMessage.Send           - Send channel messages
# - Chat.ReadWrite.All            - Read/write chats
# - Team.ReadBasic.All            - Read team info
# - User.Read.All                 - Read user profiles
# - Group.Read.All                - Read group info
# - OnlineMeetings.ReadWrite.All  - Create meetings

# Delegated permissions:
# - Chat.ReadWrite                - User chat access
# - Team.ReadBasic.All            - User team access
# - ChannelMessage.Send           - User can send messages

# 3. Create client secret:
#    - Certificates & secrets -> New client secret
#    - Save the value (shown only once)
```

### Python Environment Setup

```bash
# Create virtual environment
python -m venv teams-bot-env
source teams-bot-env/bin/activate  # Linux/macOS

# Install dependencies
pip install azure-identity msgraph-sdk botbuilder-core aiohttp

# Create requirements.txt
cat > requirements.txt << 'EOF'
azure-identity>=1.14.0
msgraph-sdk>=1.0.0
botbuilder-core>=4.14.0
botbuilder-integration-aiohttp>=4.14.0
aiohttp>=3.9.0
python-dotenv>=1.0.0
requests>=2.31.0
EOF

# Environment variables
cat > .env << 'EOF'
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
MICROSOFT_APP_ID=your-bot-app-id
MICROSOFT_APP_PASSWORD=your-bot-password
TEAMS_WEBHOOK_URL=your-webhook-url
EOF
```

### Bot Framework Registration

```bash
# 1. Go to https://dev.botframework.com/bots/new
# 2. Or use Azure Portal -> Create a resource -> Bot Channels Registration

# Bot configuration:
# - Messaging endpoint: https://your-app.azurewebsites.net/api/messages
# - Microsoft App ID: from App Registration
# - Enable Teams channel

# For local development with ngrok:
ngrok http 3978
# Update messaging endpoint to ngrok URL
```

## Core Capabilities

### 1. Microsoft Graph API Client

```python
# graph_client.py
# ABOUTME: Microsoft Graph API client for Teams operations
# ABOUTME: Handles authentication and common API calls

from azure.identity import ClientSecretCredential
from msgraph import GraphServiceClient
from msgraph.generated.models.chat_message import ChatMessage
from msgraph.generated.models.item_body import ItemBody
from msgraph.generated.models.body_type import BodyType
import os
from dotenv import load_dotenv

load_dotenv()

class TeamsGraphClient:
    """Microsoft Graph client for Teams operations"""

    def __init__(self):
        self.credential = ClientSecretCredential(
            tenant_id=os.environ["AZURE_TENANT_ID"],
            client_id=os.environ["AZURE_CLIENT_ID"],
            client_secret=os.environ["AZURE_CLIENT_SECRET"]
        )

        self.client = GraphServiceClient(
            credentials=self.credential,
            scopes=["https://graph.microsoft.com/.default"]
        )

    async def send_channel_message(
        self,
        team_id: str,
        channel_id: str,
        content: str,
        content_type: str = "html"
    ):
        """Send a message to a Teams channel"""

        message = ChatMessage(
            body=ItemBody(
                content_type=BodyType.Html if content_type == "html" else BodyType.Text,
                content=content
            )
        )

        result = await self.client.teams.by_team_id(team_id) \
            .channels.by_channel_id(channel_id) \
            .messages.post(message)

        return result

    async def send_chat_message(
        self,
        chat_id: str,
        content: str
    ):
        """Send a message to a chat (1:1 or group)"""

        message = ChatMessage(
            body=ItemBody(
                content_type=BodyType.Html,
                content=content
            )
        )

        result = await self.client.chats.by_chat_id(chat_id) \
            .messages.post(message)

        return result

    async def list_teams(self):
        """List all teams the app has access to"""
        result = await self.client.groups.get()
        teams = [g for g in result.value if g.resource_provisioning_options
                 and "Team" in g.resource_provisioning_options]
        return teams

    async def list_channels(self, team_id: str):
        """List channels in a team"""
        result = await self.client.teams.by_team_id(team_id) \
            .channels.get()
        return result.value

    async def get_channel_messages(
        self,
        team_id: str,
        channel_id: str,
        top: int = 50
    ):
        """Get recent messages from a channel"""

        result = await self.client.teams.by_team_id(team_id) \
            .channels.by_channel_id(channel_id) \
            .messages.get(
                request_configuration=lambda config:
                    setattr(config.query_parameters, 'top', top)
            )

        return result.value

    async def reply_to_message(
        self,
        team_id: str,
        channel_id: str,
        message_id: str,
        content: str
    ):
        """Reply to a channel message"""

        reply = ChatMessage(
            body=ItemBody(
                content_type=BodyType.Html,
                content=content
            )
        )

        result = await self.client.teams.by_team_id(team_id) \
            .channels.by_channel_id(channel_id) \
            .messages.by_chat_message_id(message_id) \
            .replies.post(reply)

        return result

    async def create_online_meeting(
        self,
        subject: str,
        start_time: str,
        end_time: str,
        attendees: list
    ):
        """Create an online meeting"""
        from msgraph.generated.models.online_meeting import OnlineMeeting
        from msgraph.generated.models.meeting_participants import MeetingParticipants
        from msgraph.generated.models.meeting_participant_info import MeetingParticipantInfo
        from msgraph.generated.models.identity_set import IdentitySet
        from msgraph.generated.models.identity import Identity

        participant_list = [
            MeetingParticipantInfo(
                identity=IdentitySet(
                    user=Identity(id=attendee)
                )
            )
            for attendee in attendees
        ]

        meeting = OnlineMeeting(
            subject=subject,
            start_date_time=start_time,
            end_date_time=end_time,
            participants=MeetingParticipants(
                attendees=participant_list
            )
        )

        result = await self.client.me.online_meetings.post(meeting)
        return result

    async def get_user_by_email(self, email: str):
        """Get user details by email"""
        result = await self.client.users.by_user_id(email).g

Related in communication