chore(skills): rename add-*-v2 → add-* and drop dead v1 channel skills
Renamed 13 skill folders to drop the -v2 suffix (the v2/v1 distinction isn't load-bearing anymore — there is no v1 runtime). Deleted the four v1 channel skills that occupied the rename target paths (add-discord, add-slack, add-telegram, add-whatsapp); they targeted src/v1 which is reference-only per CLAUDE.md. Skill content still says "v2" in places — that's a follow-up commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
207
.claude/skills/add-teams/SKILL.md
Normal file
207
.claude/skills/add-teams/SKILL.md
Normal file
@@ -0,0 +1,207 @@
|
||||
---
|
||||
name: add-teams-v2
|
||||
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, group chats, and direct messages.
|
||||
|
||||
## Install
|
||||
|
||||
v2 trunk doesn't ship channels. This skill copies the Teams adapter in from the `channels` branch.
|
||||
|
||||
### Pre-flight (idempotent)
|
||||
|
||||
Skip to **Credentials** if all of these are already in place:
|
||||
|
||||
- `src/channels/teams.ts` exists
|
||||
- `src/channels/index.ts` contains `import './teams.js';`
|
||||
- `@chat-adapter/teams` is listed in `package.json` dependencies
|
||||
|
||||
Otherwise continue. Every step below is safe to re-run.
|
||||
|
||||
### 1. Fetch the channels branch
|
||||
|
||||
```bash
|
||||
git fetch origin channels
|
||||
```
|
||||
|
||||
### 2. Copy the adapter
|
||||
|
||||
```bash
|
||||
git show origin/channels:src/channels/teams.ts > src/channels/teams.ts
|
||||
```
|
||||
|
||||
### 3. Append the self-registration import
|
||||
|
||||
Append to `src/channels/index.ts` (skip if the line is already present):
|
||||
|
||||
```typescript
|
||||
import './teams.js';
|
||||
```
|
||||
|
||||
### 4. Install the adapter package (pinned)
|
||||
|
||||
```bash
|
||||
pnpm install @chat-adapter/teams@4.26.0
|
||||
```
|
||||
|
||||
### 5. Build
|
||||
|
||||
```bash
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
## Credentials
|
||||
|
||||
### Step 1: Create an Azure AD App Registration
|
||||
|
||||
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
|
||||
|
||||
### Step 2: Create a Client Secret
|
||||
|
||||
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
|
||||
|
||||
Add to `.env`:
|
||||
|
||||
```bash
|
||||
TEAMS_APP_ID=your-app-id
|
||||
TEAMS_APP_PASSWORD=your-client-secret
|
||||
# For Single Tenant only:
|
||||
TEAMS_APP_TENANT_ID=your-tenant-id
|
||||
TEAMS_APP_TYPE=SingleTenant
|
||||
```
|
||||
|
||||
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 `/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.
|
||||
|
||||
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
|
||||
|
||||
If you're in the middle of `/setup`, return to the setup flow now.
|
||||
|
||||
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 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.
|
||||
Reference in New Issue
Block a user