Skip to main content
Part 2 of the Teams setup. The app package is what makes your bot appear (and be callable) in Teams: a zip with a manifest.json and two icons. All six bridges use the same package - it describes the bot identity, not the agent behind it.

Download your Teams app package

Your StandIn dashboard generates a per-identity app package with your botId and valid domains already filled in. Open your identity and click Download Teams app package (.zip) (served by /api/identities/:id/manifest), then continue to Upload to Teams.
The generated package contains no secrets - a Teams manifest is public metadata (IDs, names, icons). Anyone who obtains it can still only reach the bot your tenant consented to.
If you use the generated package you can skip straight to uploading. The rest of this page is for building or auditing the package yourself.

Example manifest

The example uses obvious placeholders - do not publish with these values.
manifest.json
{
  "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json",
  "manifestVersion": "1.23",
  "version": "1.0.0",
  "id": "00000000-0000-0000-0000-000000000000",
  "name": { "short": "StandIn", "full": "StandIn - Teams Voice & Video AI" },
  "developer": {
    "name": "Komaa",
    "websiteUrl": "https://standin.komaa.com",
    "privacyUrl": "https://komaa.com/privacy",
    "termsOfUseUrl": "https://komaa.com/terms"
  },
  "description": {
    "short": "Voice & video AI for Teams - converse, see the caller, appear as an avatar.",
    "full": "StandIn turns your Microsoft Teams bot into a Conversational Video Interface (CVI): callers talk to your AI in real time, share camera and screen, and see a lip-synced avatar on the bot tile. Subscribe at standin.komaa.com, connect your own Azure bot, and pair it with the Teams Voice Plugin for OpenClaw or Hermes Agent."
  },
  "icons": { "outline": "outline.png", "color": "color.png" },
  "accentColor": "#16A34A",
  "bots": [
    {
      "botId": "11111111-1111-1111-1111-111111111111",
      "scopes": ["personal", "team", "groupChat"],
      "isNotificationOnly": false,
      "supportsCalling": true,
      "supportsVideo": true,
      "supportsFiles": true
    }
  ],
  "validDomains": [],
  "webApplicationInfo": { "id": "11111111-1111-1111-1111-111111111111" },
  "authorization": {
    "permissions": {
      "resourceSpecific": [
        { "name": "ChannelMessage.Read.Group", "type": "Application" },
        { "name": "ChannelMessage.Send.Group", "type": "Application" },
        { "name": "Member.Read.Group", "type": "Application" },
        { "name": "Owner.Read.Group", "type": "Application" },
        { "name": "ChannelSettings.Read.Group", "type": "Application" },
        { "name": "TeamMember.Read.Group", "type": "Application" },
        { "name": "TeamSettings.Read.Group", "type": "Application" },
        { "name": "ChatMessage.Read.Chat", "type": "Application" }
      ]
    }
  }
}
Key bot fields: supportsCalling: true (required for voice) and supportsVideo: true (required for the CVI avatar tile). The resourceSpecific block is per-team consent (RSC) - granted when the app is installed in a team; it does not replace the tenant-wide Graph permissions. Official reference: Teams app manifest schema.

Placeholders

FieldExample valueReplace with
id00000000-…-000000000000A new random GUID for the app package (unique per listing; not the bot ID).
bots[].botId11111111-…-111111111111Your Entra application (client) ID (same as the Azure Bot’s MicrosoftAppId).
webApplicationInfo.idsame as botIdMust equal botId for a standard single-app bot.
validDomains[]Your StandIn host, e.g. ["standin.komaa.com"].
Generate GUIDs with uuidgen (macOS/Linux), [guid]::NewGuid() (PowerShell), or uuidgenerator.net.

Icons

The package needs a color icon (192×192 px, color.png) and an outline icon (32×32 px, transparent, outline.png). In the Developer Portal they upload under Branding; in a manual zip they sit next to the manifest.

Packaging it manually

Put the three files at the root of the archive (Teams rejects a package where they sit in a subfolder):
msteams.zip
├── manifest.json
├── color.png
└── outline.png
Zip the files themselves, not the containing folder - msteams/manifest.json inside the zip will be rejected. Bump version whenever you republish the package.
Official reference: Create a Teams app package. Next: Upload to Teams and go live.