Skip to main content
The Teams adapter connects NanoClaw to a Microsoft Teams bot. It’s built on the Chat SDK bridge (@chat-adapter/teams 4.29.0, pinned — the /add-teams skill may pin a slightly newer adapter version) and receives messages over webhooks: Azure Bot Service POSTs to NanoClaw’s shared webhook server, so Teams needs a public HTTPS URL that reaches your machine. The guided flow uses the Teams CLI: you sign in to Microsoft 365, choose a bot name, and let setup create the app registration, client secret, and Teams-managed bot. It uploads the app package and gives you an install link. The default is single-tenant; the /add-teams skill also describes manual alternatives for other tenant configurations. The bot works in team channels, group chats, and DMs (personal scope).

Prerequisites

  • A working NanoClaw install (quickstart)
  • A Microsoft 365 tenant where you can sideload custom apps — Business, EDU, or a developer tenant. Free personal Teams does not support sideloading.
  • Permission to create Microsoft Entra app registrations and upload custom apps in the target tenant
  • A way to expose port 3000 over HTTPS — ngrok, Cloudflare Tunnel, or a reverse proxy on a VPS (Azure rejects plain http:// endpoints)

Install

Teams is offered in the first-run setup wizard, or add it later by running /add-teams in Claude Code. The wizard flow:
1

Confirm prerequisites and your public URL

Setup asks for the public HTTPS base URL that forwards to NanoClaw’s webhook port, such as https://your-tunnel.example. The messaging endpoint is /webhook/teams under that URL.
2

Name the bot and sign in

Choose a name for the app and bot. Setup installs the pinned Teams CLI globally with npm, then opens Microsoft 365 sign-in. On a headless machine, use the printed device code on another device.
3

Create the app

The Teams CLI creates the Entra app registration, generates the client secret, registers a Teams-managed bot, and uploads the app package. Setup writes TEAMS_APP_ID, TEAMS_APP_PASSWORD, TEAMS_APP_TENANT_ID, and TEAMS_APP_TYPE=SingleTenant to .env.
4

Confirm who should receive the first DM

Setup shows the account used to create the bot and asks whether to wire the assistant to it. You can choose another Teams user by supplying their Microsoft Entra object ID. Nothing is wired without a confirmed target.
5

Install the app in Teams

Open the install link and click Add. The package is already uploaded; you do not need to create or upload a manifest zip. If Teams blocks custom apps, a tenant admin must enable sideloading.
6

Connect the first conversation

Setup creates the bot’s direct conversation with the confirmed user through the Bot Framework API. The wizard wires that conversation to the agent and sends the welcome message, so you do not need to message the bot first. Setup also offers to sign out of the Teams CLI; the running bot uses its app credentials, not that login.
On a rerun, either TEAMS_APP_ID or TEAMS_APP_PASSWORD in .env makes setup skip app creation and credential prompts, preventing duplicate bots after a partial install. Existing wiring stays in place. If the first run never completed wiring, send the bot a DM and use /init-first-agent or /manage-channels to connect the discovered conversation. Repair a partial credential pair instead of creating another app.
To wire team channels or more chats later, run /manage-channels. Platform IDs look like teams:<base64url-conversation-id>:<base64url-service-url>. For additional conversations, message the bot there first and wire the messaging group NanoClaw discovers, rather than constructing the ID by hand.

Platform notes

  • Webhook delivery — the bridge registers Teams on the shared webhook server (port 3000, configurable via WEBHOOK_PORT), which routes /webhook/teams to the adapter. The public URL must stay reachable — if your tunnel dies, the bot silently stops hearing messages.
  • Threads — the adapter sets supportsThreads: true, so in group channels the router forces per-thread sessions: each Teams thread gets its own agent session (unless the wiring uses agent-shared, which keeps one session across all of an agent’s messaging groups). DMs and group chats are flat — sub-threads collapse into one session. See the entity model.
  • Mentions and engagement — by default the bot only receives channel messages when @-mentioned. Plain mention wirings respond per mention; mention-sticky wirings subscribe to the thread after the first mention and then hear everything in it. To receive all channel messages without a mention, add the ChannelMessage.Read.Group RSC permission to the app manifest and re-sideload. DMs are always treated as addressed to the bot.
  • Single vs multi tenantTEAMS_APP_TYPE must match your Azure app registration. SingleTenant additionally requires TEAMS_APP_TENANT_ID; the adapter factory passes both straight to @chat-adapter/teams.
  • Interactive questions — when an agent asks a multiple-choice question, it renders as a card with buttons; clicks arrive through the same webhook route and the card updates in place to show the selection.
  • Attachments — file attachments are downloaded by the bridge and passed to the agent as data.
  • No outbound chunking — the adapter doesn’t set the bridge’s maxTextLength, so long replies post as a single message.

Troubleshooting

  • Teams channel never starts — the adapter factory returns nothing without TEAMS_APP_ID in the environment the service reads. Verify .env contains the four TEAMS_* keys (three for multi tenant), then restart the service.
  • Bot never receives messages — check that your HTTPS tunnel is running, the messaging endpoint is https://<your-public-host>/webhook/teams, and the app is installed in Teams. If the tunnel URL changed, update the endpoint with teams app update <teams-app-id> --endpoint "https://<new-host>/webhook/teams" after signing in to the Teams CLI. The webhook server logs each registered adapter and its path on startup. A 404 Unknown adapter: teams from the webhook means the adapter never registered — same fix as the channel never starting.
  • Teams refuses to install the app — your tenant may block sideloading. A tenant admin must enable it (Teams Admin Center → Teams apps → Setup policies → Upload custom apps = On). Free personal Teams can’t sideload at all — use a Microsoft 365 Business or developer tenant.
  • Auth errors from Azure Bot Service — usually a mismatched secret or tenant type: TEAMS_APP_PASSWORD must be the client secret Value (not the Secret ID), and TEAMS_APP_TYPE must match the account type chosen at registration. For an expired or mispasted secret, run teams app auth secret create <teams-app-id> after signing in, or create one under Certificates & secrets in the Azure portal. Update TEAMS_APP_PASSWORD in .env and restart NanoClaw; rerunning setup with existing credentials does not rotate them.
For service-level checks (logs, restarts, wiring queries), see troubleshooting.
Last modified on September 4, 2026