This guide explains how to run Teams apps using the Teams AI Library without relying on the ATK VS Code extension, using custom shell functions for a more controlled development experience.
Instead of using the ATK VS Code extension (which recreates devtunnels on every launch), this approach uses a long-living devtunnel and custom functions to streamline the development process.
- Dev Tunnels CLI installed
- Teams Toolkit CLI (
npm install -g @microsoft/teamsapp-cli) - Teams CLI (
npm i -g @microsoft/teams.cli@preview) - Custom functions loaded in your shell:
- Bash/Zsh: Source the
teams-dev-functions.shscript (see Bash/Zsh setup below) - PowerShell: Load the
teams-dev-functions.ps1module (see PowerShell setup below)
- Bash/Zsh: Source the
Use the tunnel creation function to create a persistent devtunnel:
Bash/Zsh:
create_tunnel <tunnel_name> <port>
# Example:
create_tunnel myteamsapp 3978PowerShell:
Create-Tunnel -TunnelName "<tunnel_name>" -Port <port>
# Example:
Create-Tunnel -TunnelName "myteamsapp" -Port 3978This function:
- Creates a new devtunnel with the specified name
- Sets up the port mapping
- Configures anonymous access
Ensure your project has the correct ATK files:
npx @microsoft/teams.cli@preview config add atk.basicUse the provisioning function to register and provision your bot:
For TypeScript projects: Run from the root directory
Bash/Zsh:
provision_ttk_localPowerShell:
Invoke-ProvisionTtkLocalFor .NET projects: Run from the TeamsApp directory
Bash/Zsh:
cd TeamsApp
provision_ttk_localPowerShell:
Set-Location TeamsApp
Invoke-ProvisionTtkLocalThis function:
- Creates
env/.env.localif it doesn't exist - Prompts for and configures
BOT_ENDPOINTandBOT_DOMAIN - Runs
teamsapp provision --env=local
You need two terminals running simultaneously:
devtunnel host <tunnel_name>Example:
devtunnel host myteamsappFor TypeScript/Node.js:
npm run devFor .NET:
dotnet run --project <project-name>- Persistent Tunnel: No need to update bot endpoints on every launch
- Better Control: Manual control over tunnel lifecycle
- Consistent URLs: Same tunnel URL across development sessions
- Cleaner Workflow: Separation of concerns between tunneling and application hosting
To use the Bash/Zsh functions, source the script in your shell session or profile:
# Load the functions (run this once per session)
source ./teams-dev-functions.sh
# Or add to your shell profile (~/.bashrc, ~/.zshrc, etc.)
echo "source $(pwd)/teams-dev-functions.sh" >> ~/.zshrcTo use the PowerShell functions, load the module in your PowerShell profile or session:
# Load the functions (run this once per session or add to your PowerShell profile)
. .\teams-dev-functions.ps1
# Or import as a module
Import-Module .\teams-dev-functions.ps1To add to your PowerShell profile permanently:
# Add to your PowerShell profile
Add-Content $PROFILE ". `"$PWD\teams-dev-functions.ps1`""Bash/Zsh: create_tunnel(tunnel_name, port)
PowerShell: Create-Tunnel -TunnelName <name> -Port <port>
Creates a new devtunnel with the specified name and port, configured for anonymous access.
Bash/Zsh: provision_ttk_local()
PowerShell: Invoke-ProvisionTtkLocal
Provisions a Teams Toolkit project for local development, handling environment configuration and bot registration.
- Ensure your devtunnel is running before starting your application server
- Verify the port in your tunnel matches the port your application is running on
- Check that
BOT_ENDPOINTinenv/.env.localmatches your tunnel URL - If you encounter issues with bot registration, verify your tunnel is accessible and anonymous access is enabled
Thanks Aamir!
CLI version of powershell script. Can be used from command line: https://gist.github.com/rajan-chari/8b1c4d8c54609a8c89c42bf7cfef3d02