Lifecycle and atk CLI
purpose
M365 Agents Toolkit lifecycle configuration (m365agents.yml) and full atk CLI command reference for provisioning, deploying, and managing M365 agents (declarative agents, custom engine agents, Teams bots/tabs/message extensions, Copilot connectors, Office add-ins).
rules
- m365agents.yml is the lifecycle manifest. Every Agents Toolkit project has an
m365agents.ymlat the project root for dev/cloud deployment, and typically anm365agents.local.ymlfor local development. They define theprovision,deploy, andpublishlifecycle stages — each stage is an ordered list of actions.atk provision --env localrunsm365agents.local.yml;atk provision --env devrunsm365agents.yml. - Lifecycle stages run in order: provision → deploy → publish. Provision creates cloud resources (Azure Bot, App Registration, resource groups). Deploy pushes app code to compute targets. Publish submits the app package to the Teams catalog.
- All actions use
uses:— there is noruns:syntax. Built-in actions likearm/deployorteamsApp/createare referenced withuses: <action-name>. Custom shell commands use the built-inscriptaction:uses: scriptwithwith.run: <command>. Every action accepts awith:block for parameters. - Built-in actions cover the full lifecycle. Key actions:
aadApp/create,aadApp/update,botAadApp/create,botFramework/create,arm/deploy,azureAppService/zipDeploy,azureFunctions/zipDeploy,teamsApp/create,teamsApp/update,teamsApp/validateManifest,teamsApp/zipAppPackage,file/createOrUpdateEnvironmentFile. TheaadApp/createaction must includegenerateServicePrincipal: true— without it, the service principal is not created and the bot getsAADSTS7000229. - Use
m365agents.ymlto replace manual Azure portal setup. A singleprovisionstage automates what otherwise requires 10+ manualazCLI commands or Azure Portal steps: Entra ID App Registration (aadApp/create), bot identity and password (botAadApp/create), Bot Service with Teams channel (botFramework/create), ARM/Bicep resource deployment (arm/deploy), and Teams app registration (teamsApp/create). Each action writes its outputs (IDs, secrets) to env files automatically. For the full manual walkthrough these actions replace, see../experts/deploy/azure-bot-deploy-ts.mdrules 3–12. environmentFolderPathinm365agents.ymlpoints to theenv/directory. Defaults to./env. All${{VAR}}placeholders resolve from the active environment's.env.{name}files.atk newscaffolds a project. Creates project structure withm365agents.yml,m365agents.local.yml,env/folder,appPackage/, and starter code. Supports--capabilityfor predefined templates and-i falsefor non-interactive mode. ATK CLI version must be > 1.1.5-beta — install withnpm i -g @microsoft/m365agentstoolkit-cli@beta.atk provisioncreates cloud resources. Runs theprovisionstage in the environment-specific YAML. Accepts--env <name>to target a specific environment (default:dev). Always add-i falsefor non-interactive execution. Creates resources defined by ARM templates or built-in actions.atk deploypushes code to cloud or generates local config. Runs thedeploystage. For cloud (--env dev), builds the project and deploys to Azure. For local (--env local), writes runtime credentials to.localConfigsviafile/createOrUpdateEnvironmentFile. Always runatk provisionbefore first deploy.atk publishsubmits to the org catalog. Runs thepublishstage. Packages the app and submits it to the Teams Admin Center for org-wide distribution. Requires admin approval after submission.atk validatechecks the manifest. Validatesmanifest.jsonagainst the Teams schema before packaging. Catches missing fields, invalid scopes, and schema violations early.atk packagecreates the app zip bundle. Generates the.zipcontainingmanifest.json, icons, and resolved placeholders. Useatk package --env <name> -i false. This is the artifact uploaded to Teams or Partner Center.atk previewlaunches local testing. Starts the Agents Playground for local testing without deploying to Teams. Seeplayground.mdfor the recommendedagentsplaygroundCLI alternative that requires no provisioning.- CI/CD integration uses
atkCLI with--envand-i falseflags. GitHub Actions and Azure Pipelines callatk provision --env staging -i falseandatk deploy --env staging -i falsein sequence. Store credentials in CI secrets, not in.env.*.userfiles.
patterns
Pattern 1: m365agents.yml anatomy (cloud deployment)
# m365agents.yml — lifecycle configuration for dev/cloud
version: v1.11
environmentFolderPath: ./env
provision:
- uses: teamsApp/create
with:
name: ${{TEAMS_APP_NAME}}
writeToEnvironmentFile:
teamsAppId: TEAMS_APP_ID
- uses: botAadApp/create
with:
name: ${{BOT_DISPLAY_NAME}}
writeToEnvironmentFile:
botId: BOT_ID
botPassword: SECRET_BOT_PASSWORD
- uses: arm/deploy
with:
subscriptionId: ${{AZURE_SUBSCRIPTION_ID}}
resourceGroupName: ${{AZURE_RESOURCE_GROUP_NAME}}
templates:
- path: ./infra/azure.bicep
parameters: ./infra/azure.parameters.json
deploymentName: teams-bot
writeToEnvironmentFile:
botEndpoint: BOT_ENDPOINT
- uses: teamsApp/zipAppPackage
with:
manifestPath: ./appPackage/manifest.json
outputZipPath: ./appPackage/build/appPackage.${{APP_ENV}}.zip
outputFolder: ./appPackage/build
- uses: teamsApp/update
with:
appPackagePath: ./appPackage/build/appPackage.${{APP_ENV}}.zip
deploy:
- uses: cli/runNpmCommand
with:
args: install
- uses: azureAppService/zipDeploy
with:
artifactFolder: .
resourceId: ${{AZURE_APP_SERVICE_RESOURCE_ID}}Pattern 1b: m365agents.local.yml anatomy (local development)
# m365agents.local.yml — lifecycle configuration for local
version: v1.11
provision:
- uses: teamsApp/create
with:
name: ${{TEAMS_APP_NAME}}-local-debug
writeToEnvironmentFile:
teamsAppId: TEAMS_APP_ID
- uses: aadApp/create
with:
name: ${{CONFIG__MANIFEST__NAME}}-aad
generateClientSecret: true
generateServicePrincipal: true # REQUIRED — without this, AADSTS7000229
signInAudience: AzureADMultipleOrgs
writeToEnvironmentFile:
clientId: BOT_ID
clientSecret: SECRET_BOT_PASSWORD
objectId: BOT_OBJECT_ID
tenantId: TEAMS_APP_TENANT_ID
- uses: botFramework/create
with:
botId: ${{BOT_ID}}
name: ${{CONFIG__MANIFEST__NAME}}
messagingEndpoint: ${{BOT_ENDPOINT}}/api/messages
description: "" # Optional — driver defaults to ""; templates set it explicitly for clarity
channels:
- name: msteams
deploy:
- uses: file/createOrUpdateEnvironmentFile
with:
target: ./.localConfigs
envs:
PORT: 3978
CLIENT_ID: ${{BOT_ID}}
CLIENT_SECRET: ${{SECRET_BOT_PASSWORD}}
TENANT_ID: ${{TEAMS_APP_TENANT_ID}}Critical:
.localConfigsis what your app reads at runtime, NOTenv/.env.local. Thefile/createOrUpdateEnvironmentFileaction transforms env vars fromenv/.env.localinto.localConfigs. In the example above,.localConfigsTENANT_IDcomes fromTEAMS_APP_TENANT_IDinenv/.env.local. IfTENANT_IDis missing from.localConfigsafter deploy, copy the value fromTEAMS_APP_TENANT_IDinenv/.env.local.
Pattern 2: Manual steps replaced by m365agents.yml
Each provision action in m365agents.yml replaces one or more manual Azure CLI / Portal steps. This table maps them:
m365agents.yml action |
Manual equivalent it replaces | What gets auto-created |
|---|---|---|
aadApp/create |
Azure Portal → App Registrations → New registration, or az ad app create + az ad app credential reset |
Entra ID App with client ID + secret, written to env |
botAadApp/create |
az ad app create (separate bot identity) + az ad app credential reset |
Bot-specific App ID + password, written to env |
botFramework/create |
az bot create --app-type SingleTenant + az bot msteams create |
Azure Bot Service resource with Teams channel connected |
arm/deploy |
az group create + az webapp create + az webapp config appsettings set (or equivalent for Functions/Container Apps) |
All Bicep/ARM resources (App Service, plan, settings) |
teamsApp/create |
Teams client → Apps → Upload a custom app, or Teams Admin Center upload | Teams app registration with TEAMS_APP_ID |
azureAppService/zipDeploy |
az webapp deploy --src-path <zip> |
Code deployed to App Service |
teamsApp/zipAppPackage |
Manually zip manifest.json + icons with resolved placeholders |
App package .zip ready for sideload or publishing |
Bottom line:
atk provision+atk deployreplaces steps 3–12 in../experts/deploy/azure-bot-deploy-ts.md. Two commands instead of ten.
Pattern 2b: Custom shell commands via uses: script
There is no runs: step in m365agents.yml. To run an arbitrary shell command, use the built-in script action:
# Set environment variables for local launch (from templates/configs/local/typescript/m365agents.local.yml.tpl)
- uses: script
with:
run:
echo "::set-teamsfx-env BOT_DOMAIN=localhost";
echo "::set-teamsfx-env BOT_ENDPOINT=https://localhost:3978";
# Run a build step in a subdirectory
- uses: script
with:
run: npm run build
workingDirectory: ./srcThe script driver also supports shell: (e.g., bash, pwsh) and redirectTo: for capturing output.
Pattern 3: CLI command reference
# Check CLI version (must be > 1.1.5-beta)
atk --version
# Install / update CLI
npm i -g @microsoft/m365agentstoolkit-cli@beta
# Scaffold a new project
atk new # Interactive wizard
atk new -c ai-bot -l typescript -i false # Non-interactive
# Provision cloud resources
atk provision --env dev -i false # Uses m365agents.yml
atk provision --env local -i false # Uses m365agents.local.yml
atk provision --env dev --resource-group <rg> --region <region> -i false # Azure resources
# Deploy application code / generate .localConfigs
atk deploy --env dev -i false # Deploy to Azure
atk deploy --env local -i false # Generate .localConfigs
# Validate and package
atk validate --env dev -i false
atk package --env dev -i false
# Publish to org catalog
atk publish --env dev -i false
# Local preview / Agents Playground
atk preview
# Update an existing Teams app registration
atk update
# Auth management
atk auth login m365
atk auth login azure
atk auth listPattern 4: GitHub Actions CI/CD pipeline
# .github/workflows/deploy.yml
name: Deploy Teams Bot
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- name: Install Agents Toolkit CLI
run: npm install -g @microsoft/m365agentstoolkit-cli
- name: Provision
run: atk provision --env production -i false
env:
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_RESOURCE_GROUP_NAME: ${{ secrets.AZURE_RESOURCE_GROUP_NAME }}
# M365 credentials for app registration
M365_ACCOUNT_NAME: ${{ secrets.M365_ACCOUNT_NAME }}
M365_ACCOUNT_PASSWORD: ${{ secrets.M365_ACCOUNT_PASSWORD }}
- name: Deploy
run: atk deploy --env production -i false
env:
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}Pattern 5: Cross-Platform Projects (no m365agents.yml)
Standalone cross-platform examples (Teams + Slack) can skip m365agents.yml entirely. These projects:
- Use a single
.envfile at the project root (loaded viadotenv) instead ofenv/.env.{name}pairs - Still include
appPackage/manifest.jsonfor sideloading into Teams - Run with
tsx watchornodedirectly — noatk provisionoratk deployneeded - Manage Azure resources manually (Bot Registration, App Service) rather than through lifecycle actions
cross-platform-bot/
├── appPackage/
│ └── manifest.json # v1.26 schema, ${{VAR}} placeholders for sideloading
├── src/
│ ├── adapters/
│ │ ├── teams-bot.ts # @microsoft/teams.apps handler
│ │ └── slack-bot.ts # @slack/bolt handler
│ └── index.ts # Starts both platforms
├── .env # All credentials (Teams + Slack) in one file
├── package.json
└── tsconfig.json # extends @microsoft/teams.config/tsconfig.node.jsonWhen to add
m365agents.yml: Only when you wantatk provision/atk deployto manage Azure resources automatically. For teaching examples and local development, manual.env+ sideloading is simpler.
pitfalls
- Running
deploybeforeprovision— Cloud resources must exist first. Always provision before the first deploy. Subsequent deploys can skip provision if resources haven't changed. - Forgetting
writeToEnvironmentFile— Built-in actions that create resources output IDs and secrets. WithoutwriteToEnvironmentFile, downstream actions can't reference these values. - Editing
m365agents.ymlaction order — Actions run top-to-bottom within a stage. Movingarm/deploybeforebotAadApp/createbreaks because the ARM template references the bot ID. - Inventing a
runs:field — There is no top-levelruns:step inm365agents.yml. For custom shell commands, use the built-inuses: scriptaction with awith.run: <command>block (and an optionalworking-directory:). - Committing
.env.*.userfiles — These contain secrets (SECRET_*vars). They're gitignored by default — don't override this. - Missing
--envin CI — Without--env, the CLI uses thedevenvironment. Production pipelines must specify--env productionexplicitly. - Confusing
atkwith legacy CLI names — The CLI was previously calledteamsfx, thenteamsapp. The current CLI isatk(installed as@microsoft/m365agentstoolkit-cli). If docs or examples referenceteamsfxorteamsapp, translate toatk. - ARM template parameter mismatches —
arm/deployparameters must match the Bicep/ARM template's expected inputs. Mismatches cause silent failures during provisioning. - Missing
generateServicePrincipal: trueinaadApp/create— Without this field, no service principal is created. The bot getsAADSTS7000229at runtime. Always include it in the local YAML'saadApp/createaction. TENANT_IDnot written to.localConfigs— Thefile/createOrUpdateEnvironmentFilemay not includeTENANT_ID. Without it, the SDK acquires tokens from the wrong authority, causing 401 from Bot Connector. Copy fromenv/.env.localif missing.- Devtunnel URL blacklisted after repeated 401s — Bot Framework may cache a failing tunnel URL. Even after fixing auth, the bot still gets 401. Create a fresh devtunnel, update
BOT_ENDPOINT, and re-provision. outputJsonPathinteamsApp/zipAppPackage— This field does not exist. UseoutputFolderinstead. Using the wrong field causes a silent schema validation error.- Assuming
descriptionis required inbotFramework/create— It is optional. The driver defaults to""when not provided. Templates setdescription: ""explicitly only for clarity, not because the schema rejects its omission. - Using
botAadApp/createin local YAML —botAadApp/createis for cloud (m365agents.yml). Local templates useaadApp/create+botFramework/createinstead.
references
- M365 Agents Toolkit overview
- m365agents.yml schema
- Provision cloud resources
- Deploy to Azure
- CI/CD with Agents Toolkit
- ATK CLI reference
instructions
Do a web search for:
- "Microsoft 365 Agents Toolkit m365agents.yml lifecycle configuration 2025"
- "atk CLI provision deploy publish commands reference"
- "Agents Toolkit CI/CD GitHub Actions Azure Pipelines"
Pair with:
../experts/teams/project.scaffold-files-ts.md— project scaffolding (whatatk newcreates)../experts/deploy/azure-bot-deploy-ts.md— manual Azure deployment as alternative to Agents Toolkitenvironments.md— environment files consumed by lifecycle hookspublish.md— detailed publishing workflow
research
Deep Research prompt:
"Write a micro expert on Microsoft 365 Agents Toolkit lifecycle management (TypeScript). Cover m365agents.yml anatomy, atk CLI commands (new, provision, deploy, publish, validate, package, preview, update), built-in actions (arm/deploy, azureAppService/deploy, aadApp/create, botAadApp/create, teamsApp/create, teamsApp/validateManifest, teamsApp/zipAppPackage), uses: vs runs: hooks, writeToEnvironmentFile, CI/CD integration with GitHub Actions and Azure Pipelines. Include canonical patterns for: complete m365agents.yml config, CLI command reference cheat sheet, GitHub Actions deployment pipeline."