From 3db0dceb1b29b25e34f3429650253a5b2d17e3b5 Mon Sep 17 00:00:00 2001 From: Gabi Simons Date: Mon, 13 Apr 2026 07:45:28 +0000 Subject: [PATCH] docs(teams-v2): full setup guide with Azure CLI, manifest, and sideloading Rewrites the add-teams-v2 skill with step-by-step instructions covering App Registration, client secret, Azure Bot creation (portal and CLI), messaging endpoint, Teams channel, manifest template, sideloading, and RSC permissions for receiving all messages. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/skills/add-teams-v2/SKILL.md | 139 +++++++++++++++++++++++---- 1 file changed, 120 insertions(+), 19 deletions(-) diff --git a/.claude/skills/add-teams-v2/SKILL.md b/.claude/skills/add-teams-v2/SKILL.md index eaed5ce..b7c3444 100644 --- a/.claude/skills/add-teams-v2/SKILL.md +++ b/.claude/skills/add-teams-v2/SKILL.md @@ -5,7 +5,7 @@ description: Add Microsoft Teams channel integration to NanoClaw v2 via Chat SDK # Add Microsoft Teams Channel -Connect NanoClaw to Microsoft Teams for interactive chat in team channels and direct messages. +Connect NanoClaw to Microsoft Teams for interactive chat in team channels, group chats, and direct messages. ## Pre-flight @@ -31,20 +31,120 @@ npm run build ## Credentials -### Create Azure Bot +### Step 1: Create an Azure AD App Registration -1. Go to [Azure Portal](https://portal.azure.com) > search **Azure Bot** > **Create** -2. Choose **Multi Tenant** (default) or **Single Tenant** depending on your org setup -3. After creation, go to **Configuration**: - - Copy the **Microsoft App ID** - - Note the **App Tenant ID** (shown for Single Tenant) - - Set **Messaging endpoint** to `https://your-domain/webhook/teams` -4. Click **Manage Password** > **Certificates & secrets** > **New client secret** — copy the Value immediately (shown only once) -5. Go to **Channels** > add **Microsoft Teams** > Accept terms > Apply +1. Go to [Azure Portal](https://portal.azure.com) > **App registrations** > **New registration** +2. Name it (e.g., "NanoClaw") +3. Supported account types: **Single tenant** (your org only) or **Multi tenant** (any org) +4. Click **Register** +5. Copy the **Application (client) ID** and **Directory (tenant) ID** from the Overview page -### Create Teams App Package +### Step 2: Create a Client Secret -Create a `manifest.json` with your App ID, zip it with two icon PNGs (32x32 outline, 192x192 color), and sideload in Teams via **Apps** > **Manage your apps** > **Upload a custom app**. Sideloading requires Teams admin or a developer tenant (free via Microsoft 365 Developer Program). +1. In the App Registration, go to **Certificates & secrets** +2. Click **New client secret**, description "nanoclaw", expiry 180 days +3. Click **Add** and **copy the Value immediately** (shown only once) + +### Step 3: Create an Azure Bot + +1. Go to Azure Portal > search **Azure Bot** > **Create** +2. Fill in: + - **Bot handle**: unique name (e.g., "nanoclaw-bot") + - **Type of App**: match your app registration (Single or Multi Tenant) + - **Creation type**: **Use existing app registration** + - **App ID**: paste from Step 1 + - **App tenant ID**: paste from Step 1 (Single Tenant only) +3. Click **Review + create** > **Create** + +Or use Azure CLI: + +```bash +az group create --name nanoclaw-rg --location eastus +az bot create \ + --resource-group nanoclaw-rg \ + --name nanoclaw-bot \ + --app-type SingleTenant \ + --appid YOUR_APP_ID \ + --tenant-id YOUR_TENANT_ID \ + --endpoint "https://your-domain/api/webhooks/teams" +``` + +### Step 4: Configure Messaging Endpoint + +1. Go to your Azure Bot resource > **Configuration** +2. Set **Messaging endpoint** to `https://your-domain/api/webhooks/teams` +3. Click **Apply** + +### Step 5: Enable Teams Channel + +1. In the Azure Bot resource, go to **Channels** +2. Click **Microsoft Teams** > Accept terms > **Apply** + +Or via CLI: + +```bash +az bot msteams create --resource-group nanoclaw-rg --name nanoclaw-bot +``` + +### Step 6: Create and Sideload Teams App + +Create a `manifest.json`: + +```json +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.16/MicrosoftTeams.schema.json", + "manifestVersion": "1.16", + "version": "1.0.0", + "id": "YOUR_APP_ID", + "packageName": "com.nanoclaw.bot", + "developer": { + "name": "NanoClaw", + "websiteUrl": "https://your-domain", + "privacyUrl": "https://your-domain", + "termsOfUseUrl": "https://your-domain" + }, + "name": { "short": "NanoClaw", "full": "NanoClaw Assistant" }, + "description": { + "short": "NanoClaw assistant bot", + "full": "NanoClaw personal assistant powered by Claude." + }, + "icons": { "outline": "outline.png", "color": "color.png" }, + "accentColor": "#4A90D9", + "bots": [{ + "botId": "YOUR_APP_ID", + "scopes": ["personal", "team", "groupchat"], + "supportsFiles": false, + "isNotificationOnly": false + }], + "permissions": ["identity", "messageTeamMembers"], + "validDomains": ["your-domain"] +} +``` + +Create two icon PNGs (32x32 `outline.png`, 192x192 `color.png`), zip all three files together. + +**Sideload in Teams:** +1. Open Teams > **Apps** > **Manage your apps** +2. Click **Upload an app** > **Upload a custom app** +3. Select the zip file + +Sideloading requires Teams admin access. Free personal Teams does NOT support sideloading. Use a Microsoft 365 Business account or developer tenant. + +### Step 7: Receive All Messages (Optional) + +By default, the bot only receives messages when @-mentioned. To receive all messages in a channel without @-mention, add RSC permissions to `manifest.json`: + +```json +{ + "authorization": { + "permissions": { + "resourceSpecific": [ + { "name": "ChannelMessage.Read.Group", "type": "Application" } + ] + } + } +} +``` ### Configure environment @@ -62,9 +162,9 @@ Sync to container: `mkdir -p data/env && cp .env data/env/env` ### Webhook server -The Chat SDK bridge automatically starts a shared webhook server on port 3000 (configurable via `WEBHOOK_PORT` env var). The server handles `/webhook/teams` for Teams and other webhook-based adapters. This port must be publicly reachable from the internet for Azure Bot Service to deliver activities. +The Chat SDK bridge automatically starts a shared webhook server on port 3000 (configurable via `WEBHOOK_PORT` env var). The server handles `/api/webhooks/teams` for Teams and other webhook-based adapters. This port must be publicly reachable from the internet for Azure Bot Service to deliver activities. -If running locally, discuss options for exposing the server — e.g. ngrok (`ngrok http 3000`), Cloudflare Tunnel, or a reverse proxy on a VPS. The resulting public URL becomes the base for `https://your-domain/webhook/teams`. +For local development without a public URL, use a tunnel (e.g., `ngrok http 3000`) and update the messaging endpoint in Azure Bot Configuration. ## Next Steps @@ -75,8 +175,9 @@ Otherwise, run `/manage-channels` to wire this channel to an agent group. ## Channel Info - **type**: `teams` -- **terminology**: Teams has "teams" containing "channels." The bot can also receive direct messages. Teams channels can have threaded replies. -- **how-to-find-id**: Right-click a channel in Teams > "Get link to channel" -- the channel ID is in the URL. Or use the Microsoft Graph API to list channels. -- **supports-threads**: yes -- **typical-use**: Interactive chat -- team channels or direct messages -- **default-isolation**: Same agent group for channels where you're the primary user. Separate agent group for channels with different teams or where different members have different information boundaries. +- **terminology**: Teams has "teams" containing "channels." The bot can also receive DMs (personal scope) and group chat messages. Channels support threaded replies. +- **platform-id-format**: `teams:{base64-encoded-conversation-id}:{base64-encoded-service-url}` — auto-generated by the adapter, not human-readable. Use the auto-created messaging group ID for wiring. +- **how-to-find-id**: Send a message to the bot in the channel. NanoClaw auto-creates a messaging group and logs the platform ID. Use that messaging group ID for wiring. +- **supports-threads**: yes (channels only; DMs and group chats are flat) +- **typical-use**: Team collaboration with the bot in channels; personal assistant via DMs +- **default-isolation**: Separate agent group per team. DMs can share an agent group with your main channel for unified personal memory.