Skip to content

Teams Agent Preflight FAQ

preflight.sh (Linux/macOS) and preflight.ps1 (Windows) check your machine and accounts before you run setup. Find your failed check below, apply the fix, run again.


How preflight works

Preflight only reads. It installs nothing and creates nothing in Azure or Microsoft 365. Run it, fix every FAIL, run again, then run setup.sh / setup.ps1. Setup does not run preflight for you.

Checks run in stages. A failed stage stops the run, so later checks stay hidden until you fix it. WARN never blocks.

Stage Check Passes when If not
1 Prerequisites python3, node, npm, az, atk Command found. Version printed, no minimum enforced FAIL, stop. Tools not installed
1 Prerequisites PowerShell policy (Windows) Not Restricted FAIL. PowerShell policy
2 Auth Azure login az account show works FAIL, stop. Azure login
2 Auth Teams/M365 login atk auth list shows an account FAIL, stop. M365 login
2 Auth Azure tenant Active subscription tenant = tenant of the first subscription in az account list FAIL, stop. Azure tenant mismatch
3 Permissions Azure RBAC Owner or Contributor on the subscription (direct assignment) FAIL, or WARN. Azure RBAC
3 Permissions Entra ID app registration Application Administrator or Global Administrator FAIL. Entra ID app registration
3 Permissions Teams publish Teams Administrator or Global Administrator FAIL. Teams publish role
4 Environment npm global bin Folder is on PATH WARN. Warnings
4 Environment Proxy env vars HTTP_PROXY / HTTPS_PROXY / NO_PROXY not set WARN. Warnings

On Windows the last stage is called Windows QA, and there is no separate npm row. Same checks otherwise.

The run ends with PASS (no FAIL, WARN allowed) or FAIL, plus OK / FAIL / WARN counts. The exit code is 0 either way, so read the summary line.

Not checked: MCP URL reachable, Tursio API key valid, OpenAI key or model valid, Azure name or quota limits.

Reading the output

All pass (Windows) Missing tools stop the run (Linux)
Preflight passing on Windows Preflight stopping on missing tools on Linux
Every row OK. Summary: PASS, ready to run setup.ps1. npm and atk missing. Preflight prints STOP and skips Auth and Permissions. Install, run again.

Fixes

Tools not installed

Tool Install
python3 / python Python 3.11+. Linux/macOS: python.org/downloads. Windows: python-3.12.10-amd64.exe, tick Add Python to PATH and Install for all users
node, npm Node.js 18+ from nodejs.org/en/download. npm comes with it
az Azure CLI: aka.ms/installazurecli. Check with az --version
atk npm install -g @microsoft/m365agentstoolkit-cli@1.1.17

Windows, python still not found: Settings → Apps → Advanced app settings → App execution aliases, turn off the python.exe store alias.

Old teamsapp CLI installed? Remove it before installing atk. Both packages install a command named teamsapp:

npm uninstall -g @microsoft/teamsapp-cli
setup.sh removes it for you if found.

PowerShell policy (Windows)

Policy is Restricted and blocks scripts. Run:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Run preflight again.

Azure login

az login --use-device-code
Follow the device-code prompt.

M365 login

atk auth login m365
Browser opens. Sign in with your Microsoft 365 account.

Azure tenant mismatch

Tenant of your active subscription differs from the tenant of the first subscription in az account list. Preflight treats the first one as expected.

  1. az account list --output table
  2. az account set --subscription <subscription-id>
  3. Run preflight again.

Azure RBAC

Account lacks Contributor or Owner on the subscription. Subscription comes from AZURE_SUBSCRIPTION_ID in env/.env.dev, else your active one. Preflight sees roles assigned directly to you. A role granted only through a group may not show.

  • Contributor: enough for most installs.
  • Owner: needed only if you also manage role assignments.

Ask your Azure admin: Azure Portal → Subscriptions → [subscription] → Access control (IAM) → Add role assignment.

WARN, not FAIL: could not query role assignments (run az login --use-device-code, run again) or no subscription found (az account set --subscription <id>, run again).

Entra ID app registration

Account lacks Application Administrator (or Global Administrator) in Entra ID. Ask your Entra admin: Azure Portal → Microsoft Entra ID → Roles and administrators → Application Administrator → Add assignments.

Teams publish role

Publishing to the org catalog needs Teams Administrator (or Global Administrator). Ask your Microsoft 365 admin: Microsoft 365 admin center → Roles → Role assignments → Teams Administrator.

Only one person may upload apps? Run setup with --skip-publish (-SkipPublish on Windows) and give the package zip to that person.

Role check fails but you hold the role

Preflight reads your directory roles from Microsoft Graph. If that call fails, the role list is empty and both role checks report FAIL. Causes:

  • Not signed in to Azure CLI: az login --use-device-code
  • Conditional-access policy blocks the Graph call
  • Transient network or token problem

Test the call yourself:

az rest --method GET --url "https://graph.microsoft.com/v1.0/me/transitiveMemberOf/microsoft.graph.directoryRole?\$select=displayName" --query "value[].displayName" -o tsv
Roles listed: you have them. Error shown: fix that, run preflight again.

Warnings

Do not stop install.

  • npm global bin: npm's global folder may not be on PATH. Add it, open a new terminal. atk not found after install means this.
  • Proxy env vars: HTTP_PROXY, HTTPS_PROXY or NO_PROXY is set. It may break az, npm, atk. If installs time out, unset them for the run or allow the Microsoft endpoints.

After preflight: what setup builds

Not checked by preflight. Preflight creates nothing. Later, setup.sh / setup.ps1 builds four things in one Azure resource group. All names start bot + your resource suffix (example acme gives botacme). Suffix: lowercase letters and digits, whole name 4 to 20 chars. Pick once: changing it later makes a second deployment, not a rename. Region: westus2.

# Azure resource Name What it is for
1 Managed identity (user-assigned) bot<suffix> Bot identity. Its client ID is the bot app ID. No password to store or rotate
2 App Service plan (Linux) bot<suffix> Compute. Size B2. Run one instance only: the agent keeps schedules and chat history itself
3 Web App bot<suffix> Runs the agent (python app.py, Python 3.12, always on). Listens on /api/messages. Holds all settings
4 Azure Bot bot<suffix> Front door for Teams. Plan F0, user-assigned identity, Teams channel on. Points to the Web App

In Microsoft 365: one Teams app. Setup creates it, packages it, publishes it to the org catalog.

You bring these (preflight does not check them):

  • Tursio MCP server: public https URL ending /mcp, reachable from Azure.
  • Tursio API key: Tursio portal, Settings, API Agent.
  • OpenAI model: Azure OpenAI (endpoint, key, deployment name) or standard OpenAI (key, model id). Use gpt-5 or later. Not -chat models: they fail while SHOW_REASONING is on (setup default).

No database, storage account, Key Vault or App Insights is created.

How the parts connect

Teams user
   |  message
Teams (Microsoft 365)  <-- Teams app (manifest, bot ID = identity client ID)
   |
Azure Bot  (Teams channel)
   |  HTTPS POST  https://bot<suffix>.azurewebsites.net/api/messages
Web App  bot<suffix>  <-- runs under managed identity bot<suffix>
   |-- OpenAI / Azure OpenAI   (OPENAI_API_KEY or AZURE_OPENAI_API_KEY + ENDPOINT, OPENAI_MODEL_NAME)
   |-- Tursio MCP server       (MCP_SERVER_URL, Authorization: Bearer TURSIO_API_KEY, X-Tursio-User)
        |
     Tursio data
  • Azure Bot and Web App share one identity. Bot app ID = identity client ID. The Web App gets the same client ID and tenant ID in CONNECTIONS__SERVICE_CONNECTION__SETTINGS__*, auth type UserManagedIdentity, empty secret. That is how the Web App proves it is the bot.
  • Azure Bot endpoint = Web App host + /api/messages. Setup checks it after deploy and fixes it with az bot update if wrong.
  • Web App settings carry the rest: model, MCP URL, Tursio API key, agent name (BRAND_NAME), SCHEDULE_TIMEZONE, SHOW_REASONING, REASONING_EFFORT.
  • Every MCP call uses one shared API key as bearer. User name goes in X-Tursio-User.
  • Keys are plain App Service settings. Limit who can access the resource group.

Setup steps

Setup only checks python3, node, az are on PATH, then asks you to run preflight if not.

  1. Questions: agent name, Teams app suffix, resource suffix, MCP URL, Tursio API key, OpenAI provider, key, model, schedule timezone.
  2. az login, pick subscription. atk auth login m365.
  3. atk provision: Teams app, resource group, the four resources. Skipped on Redeploy to existing resource group.
  4. atk deploy: zip push. Bot endpoint check.
  5. atk package, atk publish. --skip-publish (-SkipPublish on Windows) stops after package.

setup.ps1 banner, questions and configuration summary

Above: start of setup.ps1. The banner says to run preflight first. Saved answers show in brackets, Enter keeps them. Setup prints a summary and waits for y before it changes anything.