Skip to content

Add host-owned ASGI route registration#484

Open
dcaayushd wants to merge 3 commits into
microsoft:mainfrom
dcaayushd:fix/447-activity-entity-validation
Open

Add host-owned ASGI route registration#484
dcaayushd wants to merge 3 commits into
microsoft:mainfrom
dcaayushd:fix/447-activity-entity-validation

Conversation

@dcaayushd

Copy link
Copy Markdown
Contributor

Summary

Fixes #447.

Adds a public lifecycle split for host-owned ASGI integrations:

  • Adds App.register_routes() to synchronously register the Teams messaging endpoint without starting a server or running async plugin init.
  • Adds App.start_plugins() so hosts can run plugin on_init hooks later from their ASGI startup lifecycle.
  • Returns a public HttpRoute route table from registration.
  • Ships StarletteAdapter as part of microsoft_teams.apps.http instead of leaving it example-only.
  • Updates host-owned FastAPI/Starlette examples and docs to use the new lifecycle.

Validation

./.venv/bin/python -m pytest packages/apps/tests packages/botbuilder/tests
./.venv/bin/python -m ruff check packages/apps/src/microsoft_teams/apps packages/apps/tests/test_app.py packages/apps/tests/test_http_server.py examples/a2a/src/main.py examples/http-adapters/src/fastapi_non_managed.py examples/http-adapters/src/starlette_echo.py examples/mcp-server/src/main.py
./.venv/bin/pyright packages/apps/src/microsoft_teams/apps packages/botbuilder/src/microsoft_teams/botbuilder/adapter.py examples/a2a/src/main.py examples/http-adapters/src/fastapi_non_managed.py examples/http-adapters/src/starlette_echo.py examples/mcp-server/src/main.py

@lilyydu

lilyydu commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Hey @dcaayushd ,

Thanks for jumping on this! This looks like we're headed in the right direction - though I don't have a strong pref towards shipping the StarletteAdapter as apart of apps - @heyitsaamir do you have any particular ops?

Copilot AI review requested due to automatic review settings July 6, 2026 18:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a first-class “host-owned ASGI lifecycle” integration for the Teams Python SDK by splitting synchronous route registration from async plugin initialization, and by shipping a supported Starlette adapter.

Changes:

  • Added App.register_routes() (sync) and App.start_plugins() (async) to support caller-owned ASGI app lifecycles while keeping plugin on_init decoupled from route contribution.
  • Updated HttpServer.initialize() to return a public HttpRoute table and to expose HttpServer.routes.
  • Promoted StarletteAdapter from example-only to a shipped adapter and updated docs/examples/tests accordingly.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/apps/src/microsoft_teams/apps/app.py Adds lifecycle split (register_routes, start_plugins) and internal flags for initialization state.
packages/apps/src/microsoft_teams/apps/http/http_server.py Returns and stores HttpRoute registrations; adds routes accessor.
packages/apps/src/microsoft_teams/apps/http/adapter.py Introduces HttpRoute as a framework-agnostic route table entry.
packages/apps/src/microsoft_teams/apps/http/starlette_adapter.py Ships Starlette-based adapter implementation with managed/non-managed lifecycle behavior.
packages/apps/src/microsoft_teams/apps/http/init.py Exports HttpRoute and StarletteAdapter from the http package.
packages/apps/src/microsoft_teams/apps/init.py Re-exports HttpRoute and StarletteAdapter at the apps package level.
packages/apps/tests/test_app.py Adds coverage for the new register_routes() / start_plugins() lifecycle split.
packages/apps/tests/test_http_server.py Updates HttpServer tests for route-table return + adds StarletteAdapter tests.
packages/apps/README.md Documents the host-owned ASGI lifecycle pattern for FastAPI and Starlette hosts.
examples/http-adapters/src/fastapi_non_managed.py Updates non-managed FastAPI example to use register_routes() + start_plugins().
examples/http-adapters/src/starlette_echo.py Updates Starlette example to use shipped StarletteAdapter.
examples/http-adapters/README.md Updates adapter examples documentation to reflect the new lifecycle split and shipped adapter.
examples/http-adapters/pyproject.toml Updates example description to match shipped-adapter framing.
examples/mcp-server/src/main.py Ensures Teams routes are registered before mounting MCP app (route priority), now via register_routes().
examples/a2a/src/main.py Ensures Teams routes are registered synchronously before host-owned route table is finalized.
Comments suppressed due to low confidence (1)

packages/apps/src/microsoft_teams/apps/http/starlette_adapter.py:77

  • StarletteAdapter.start() reuses an existing uvicorn.Server instance, which can cause start(port) to silently ignore a new port value and can prevent clean restarts after stop() (since stop() sets should_exit but the adapter keeps _server). Recreate the server when the requested port differs or when the previous server was asked to exit, so start() reliably honors its port argument.

Comment thread packages/apps/src/microsoft_teams/apps/app.py
Comment thread packages/apps/src/microsoft_teams/apps/app.py
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support hosting the Teams endpoint inside a caller-owned ASGI app (sync route registration, host owns lifecycle)

3 participants