Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Teams, Agent 365, and other webhook callers deliver requests from their own servers, not a browser — so your endpoint must be reachable on the public internet over HTTPS, even while developing on localhost. A tunnel gives your local server a public URL for exactly this: bots, message extensions, Agent 365 callbacks, and any other inbound webhook your app registers. Once you deploy to a real host, you don't need a tunnel.
Dev Tunnels (recommended)
Dev Tunnels is Microsoft's tunneling service, built into Visual Studio, VS Code, and the Microsoft 365 Agents Toolkit. A persistent tunnel keeps the same hostname across restarts, so you register your endpoint once.
Install:
# macOS / Linux
brew install devtunnel
# Windows (winget)
winget install Microsoft.devtunnel
Create a persistent, anonymous-access tunnel:
devtunnel user login
devtunnel create my-teams-app --allow-anonymous
devtunnel port create my-teams-app -p 3978
devtunnel host my-teams-app
Use the printed public URL (always HTTPS) as your --endpoint:
teams app create \
--name my-bot \
--endpoint https://my-teams-app-3978.usw2.devtunnels.ms/api/messages \
--env .env
Alternatives
ngrok and Cloudflare Tunnel work the same way: start a tunnel, get a public HTTPS URL, use it as your --endpoint. Fine substitutes if you're already using one — see their docs for setup.
Verifying the tunnel reaches your app
curl -i https://<your-tunnel-host>/api/messages
Any response from your app — even an error like 401 or 404 — confirms the tunnel is forwarding correctly; move on and test from Teams. No response or a 502 means transport is broken — see Troubleshooting.
Persistent vs. ephemeral URLs
A Dev Tunnels persistent tunnel (devtunnel create <tunnel-id>) keeps its hostname across restarts, so you register the endpoint once. ngrok's free tier assigns a new hostname every run, so you must re-register (teams app update <id> --endpoint ...) each time — and possibly reinstall the app in Teams if the client cached the old endpoint.
Warning
--allow-anonymous makes the tunnel public. Anyone with the URL can reach it — required so Teams (not a Dev Tunnels client) can call your endpoint. It doesn't replace app-level auth: keep JWT/activity validation on, and delete the tunnel (devtunnel delete <tunnel-id>) when you're done.
Managing a persistent Dev Tunnel
devtunnel host my-teams-app # start (after the one-time create/port setup above)
# Ctrl+C to stop
devtunnel host my-teams-app # reuse later — same command, same hostname
devtunnel delete my-teams-app # delete when no longer needed
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
502 Bad Gateway |
Tunnel port protocol doesn't match your app | devtunnel port delete my-teams-app -p 3978, then devtunnel port create my-teams-app -p 3978 --protocol http |
| Teams can't reach bot / install fails | Tunnel not hosting, or --endpoint doesn't match current URL |
Confirm devtunnel host is running; re-check the registered endpoint |
| Worked yesterday, not today | Hostname changed (ngrok) or host process stopped | Re-run the host command; re-register the endpoint if the hostname changed |
curl hangs or times out |
Host process isn't running, or wrong port tunneled | Check the port your app actually logged on startup |
curl works, Teams doesn't |
Transport is fine; likely an app-auth issue | See Authentication Troubleshooting |
Related pages
- Running in Teams: TypeScript · C# · Python — end-to-end registration and sideload flow
- CLI reference — the same setup via
teams app create/update - Teams Core Concepts — where the tunnel fits among app registration and sideloading
- Azure Configuration — pointing an Azure Bot resource's messaging endpoint at your tunnel