> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hellofriday.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Microsoft Teams

> Connect a Microsoft Teams bot to a space for DMs and @mentions.

Connect a Microsoft Teams bot to any Friday space so users can chat with it over DM or `@mentions`. Messages flow into the same conversation pipeline the web chat uses, and replies go back to Teams.

You create the Azure Bot at [portal.azure.com](https://portal.azure.com), build a Teams app package, and connect via Studio.

## Prerequisites

* An Azure account with an active subscription. The **F0** pricing tier for Azure Bot is free and sufficient for development.
* Admin rights in a Microsoft 365 tenant that lets you sideload custom Teams apps. A personal Microsoft account ("Teams free") does **not** work — you need a work/school tenant or a Microsoft 365 Developer Program tenant.
* Friday running with the bundled tunnel active (Azure Bot requires a public HTTPS URL — `http://` is rejected).

## Setup

<Steps>
  <Step title="Create the Azure Bot">
    1. Open [portal.azure.com](https://portal.azure.com) and click **Create a resource** → search for **Azure Bot**.
    2. Fill in:
       * **Bot handle** — a unique identifier, e.g. `friday-studio-bot`
       * **Pricing tier** — **F0** (free)
       * **Type of App** — **Single Tenant** if you only plan to install into one M365 tenant; **Multi Tenant** for cross-tenant distribution. This choice is **immutable** — see [SingleTenant vs MultiTenant](#singletenant-vs-multitenant).
       * **Creation type** — **Create new Microsoft App ID**
    3. Click **Review + create** → **Create**. Provisioning takes 30–60s.

    <Warning>
      The **Type of App** dropdown is permanently greyed out after the bot exists. If you pick the wrong one, you have to delete and recreate the Azure Bot resource.
    </Warning>
  </Step>

  <Step title="Collect three credentials">
    From the Bot resource you just created:

    | Value                     | Where                                                                                 |
    | ------------------------- | ------------------------------------------------------------------------------------- |
    | **Microsoft App ID**      | Bot resource → **Configuration** → *Microsoft App ID*                                 |
    | **Client secret value**   | **Manage Password** → *Certificates & secrets* → **New client secret** → copy *Value* |
    | **Directory (tenant) ID** | App Registration → **Overview** → *Directory (tenant) ID*                             |

    The tenant ID is only required for SingleTenant bots, but it's harmless to set either way.

    <Warning>
      Azure only shows the client secret **value** once. Copy it immediately — if you miss it, delete the secret and create a new one.
    </Warning>
  </Step>

  <Step title="Connect Teams in Studio">
    1. In Studio, select your space from the sidebar and click **Info**.
    2. Find the **Communicators** card and click **Connect** next to **Microsoft Teams**.
    3. Paste the **App ID**, **Client Secret**, **Tenant ID**, and select the **App Type** (SingleTenant or MultiTenant) into the form, then submit.

    Studio stores the credentials securely. The status flips to **Connected** when it's done.
  </Step>

  <Step title="Point Azure at your messaging endpoint">
    1. Open Studio → **Settings** → **Webhook tunnel** and copy the URL — something like `https://<random>.trycloudflare.com`.
    2. In the Azure portal, open your Bot resource → **Configuration** → **Messaging endpoint** and set it to `<tunnel>/platform/teams`, e.g. `https://<random>.trycloudflare.com/platform/teams`.
    3. Click **Apply**.
    4. Under **Channels**, click **Microsoft Teams**, accept the ToS, and enable the channel.
  </Step>

  <Step title="Build and sideload a Teams app package">
    Azure Bot is the API endpoint; the Teams app package is what puts your bot in front of real users. It's a zip containing `manifest.json` plus two icons.

    1. Create a directory with this `manifest.json` (replace `<APP_ID>` with your Microsoft App ID):
       ```json manifest.json theme={null}
       {
         "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
         "manifestVersion": "1.16",
         "version": "1.0.0",
         "id": "<APP_ID>",
         "packageName": "com.yourco.friday",
         "developer": {
           "name": "Your Team",
           "websiteUrl": "https://example.com",
           "privacyUrl": "https://example.com/privacy",
           "termsOfUseUrl": "https://example.com/terms"
         },
         "icons": { "color": "color.png", "outline": "outline.png" },
         "name": { "short": "Friday", "full": "Friday Teams" },
         "description": {
           "short": "Friday agent orchestration",
           "full": "Chat with your Friday space from Teams."
         },
         "accentColor": "#4F46E5",
         "bots": [
           { "botId": "<APP_ID>", "scopes": ["personal"], "isNotificationOnly": false, "supportsFiles": false }
         ],
         "permissions": ["identity", "messageTeamMembers"],
         "validDomains": []
       }
       ```
    2. Drop a **192×192 PNG** named `color.png` and a **32×32 PNG** named `outline.png` beside the manifest.
    3. Zip those three files (manifest must be at the root of the archive, not inside a subfolder).
    4. In Teams, go to **Apps** → **Manage your apps** → **Upload an app** → **Upload a custom app** and pick the zip.
    5. Click **Add** when Teams prompts. The bot appears in your apps list.
  </Step>

  <Step title="Talk to your bot">
    1. Open the bot's app page in Teams and click **Chat** to start a DM.
    2. Send a message. The first message creates a chat in the space — it should appear in Studio with a **TEAMS** badge, and replies flow back to Teams automatically.
    3. To `@mention` the bot in a channel, add the app to the team first, then `@<bot-name> hello`.
  </Step>
</Steps>

## SingleTenant vs MultiTenant

| Type             | Tenant ID required | When to pick                                                          |
| ---------------- | ------------------ | --------------------------------------------------------------------- |
| **SingleTenant** | Yes                | You only install the bot into your own M365 tenant (most dev setups). |
| **MultiTenant**  | No                 | The same bot will be installed across multiple tenants (SaaS).        |

The **App Type** you select in Studio's connect form must match what the Azure Bot was created as. Mismatched values produce an `Authorization has been denied for this request` on outbound replies — inbound routing still looks fine, which makes it easy to miss.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Inbound activities arrive but outbound replies 401">
    `app_type` doesn't match the Bot Service's registered Type of App. Check Azure Bot → **Configuration** → *Type of App* and reconnect via Studio with the matching value.
  </Accordion>

  <Accordion title="Bot is installed in Teams but receives no messages">
    Most likely the **Teams channel isn't enabled** in Azure. Go to Bot resource →
    **Channels** → click **Microsoft Teams** → accept ToS and enable. Second most
    likely: the messaging endpoint in Azure points at a stale tunnel URL.
  </Accordion>

  <Accordion title="Inbound 401 (not outbound)">
    The incoming JWT is being rejected. Usual causes: the App ID you pasted
    doesn't match the Bot's Microsoft App ID, or a missing tenant ID on a
    SingleTenant bot.
  </Accordion>

  <Accordion title="Tunnel URL keeps changing">
    The bundled Cloudflare quick-tunnel gets a new random URL every restart. Each restart requires updating the **Messaging endpoint** in the Azure portal. For stable development, use a named Cloudflare tunnel, ngrok paid, or a real reverse proxy on your own domain.
  </Accordion>
</AccordionGroup>

## Production notes

* Rotate the client secret under *App Registration → Certificates & secrets*. Azure doesn't let you edit an existing secret — create a new one, reconnect via Studio with the new value, then delete the old one.
* Client secrets expire (default 24 months). When they do, every outbound reply returns 401 until you rotate.

## Configure via YAML

For CI or fully scripted setups, paste credentials directly into `workspace.yml` or the `.env` file in the Friday home directory (default `~/.friday/local/.env`). `app_id` is always required.

<Tabs>
  <Tab title="Credentials inline">
    ```yaml workspace.yml theme={null}
    communicators:
      teams:
        kind: teams
        app_id: 05ad3c58-7bfc-41d6-a249-011a6fe5337b
        app_password: <client secret value>
        app_tenant_id: <directory tenant id>
        app_type: SingleTenant  # or MultiTenant — must match Azure Bot's registered Type of App
    ```
  </Tab>

  <Tab title="Credentials via env">
    ```bash # Friday home .env (default ~/.friday/local/.env) theme={null}
    TEAMS_APP_ID=05ad3c58-7bfc-41d6-a249-011a6fe5337b
    TEAMS_APP_PASSWORD=<client secret value>
    TEAMS_APP_TENANT_ID=<directory tenant id>
    TEAMS_APP_TYPE=SingleTenant
    ```

    ```yaml workspace.yml theme={null}
    communicators:
      teams:
        kind: teams
    ```
  </Tab>
</Tabs>

Restart Friday so the new config is picked up.
