MSTeams extension package - #433
Conversation
…into users/robrandao/teams-turn-context
There was a problem hiding this comment.
Pull request overview
This PR adds a new Microsoft Teams hosting integration package and extends the activity model, while also refactoring core hosting types for improved type safety and consistency.
Changes:
- Introduces
microsoft_agents.hosting.msteamswithTeamsAgentExtension, Teams-specific route namespaces (channels/teams/messages/task modules/etc.), and internal helpers. - Adds
ActivityTreatment/ActivityTreatmentTypesto the activity entity model. - Refactors core hosting type definitions and a few core behaviors (e.g.,
HandoffHandlerprotocol,TurnContext.send_activityreturn type,Authorizationconnection naming).
Reviewed changes
Copilot reviewed 65 out of 71 changed files in this pull request and generated 20 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/hosting_msteams/init.py | New test package marker for Teams hosting tests. |
| tests/hosting_msteams/helpers.py | Adds shared mocks for Teams hosting tests. |
| tests/hosting_msteams/test_utils.py | Adds unit tests for Teams hosting internal utility helpers. |
| tests/hosting_msteams/test_teams_agent_extension.py | Tests TeamsAgentExtension top-level namespaces and caching behavior. |
| tests/hosting_msteams/test_team_lifecycle.py | Tests team lifecycle conversation-update routing selectors. |
| tests/hosting_msteams/test_task_modules.py | Tests task module invoke routing and handler wrapping. |
| tests/hosting_msteams/test_messages.py | Tests message update + actionable message routing and handler behavior. |
| tests/hosting_msteams/test_message_extensions.py | Tests messaging extension invoke routing and handler behavior. |
| tests/hosting_msteams/test_meetings.py | Tests meeting event routing and payload parsing. |
| tests/hosting_msteams/test_file_consent.py | Tests file consent invoke routing and payload parsing. |
| tests/hosting_msteams/test_config.py | Tests Teams config invoke routing and response behavior. |
| tests/hosting_msteams/test_channels.py | Tests channel lifecycle + member events routing and payload parsing. |
| test_samples/teams/conversation-agent/src/init.py | New Teams conversation-agent sample package init. |
| test_samples/teams/conversation-agent/src/start_server.py | Adds aiohttp startup for the Teams conversation-agent sample. |
| test_samples/teams/conversation-agent/src/main.py | Adds executable entrypoint for the Teams conversation-agent sample. |
| test_samples/teams/conversation-agent/src/agent.py | Adds the Teams conversation-agent sample implementation using the extension API. |
| test_samples/teams/conversation-agent/pyproject.toml | Adds packaging/deps for the Teams conversation-agent sample. |
| test_samples/teams/conversation-agent/env.TEMPLATE | Adds sample env template for auth settings. |
| libraries/microsoft-agents-hosting-teams/microsoft_agents/hosting/teams/teams_info.py | Removes legacy TeamsInfo implementation (deleted file). |
| libraries/microsoft-agents-hosting-teams/microsoft_agents/hosting/teams/init.py | Removes legacy Teams hosting package export surface (deleted file). |
| libraries/microsoft-agents-hosting-msteams/setup.py | Adds setup-time dynamic version/dependency wiring for the new package. |
| libraries/microsoft-agents-hosting-msteams/readme.md | Updates package README (PyPI badge/install instructions, package overview). |
| libraries/microsoft-agents-hosting-msteams/pyproject.toml | Renames distribution to microsoft-agents-hosting-msteams. |
| libraries/microsoft-agents-hosting-msteams/MANIFEST.in | Includes VERSION.txt in source distribution. |
| libraries/microsoft-agents-hosting-msteams/LICENSE | Adds package license file. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/init.py | New public exports for Teams hosting integration. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/_utils.py | Adds internal helpers (selector matching, channel_data parsing, invoke responses). |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/type_defs.py | Adds shared Teams routing type aliases/protocols. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/route_handlers.py | Adds wrappers to adapt Teams handlers to core route handler shape. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/teams_turn_context.py | Adds Teams-specific TurnContext wrapper + targeted-send helpers. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/teams_api_client.py | Adds TurnContext-scoped Teams API client caching/creation. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/teams_agent_extension.py | Adds main Teams extension aggregating route namespaces and wrapping core decorators. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/teams_activity.py | Adds Teams-specific Activity subclass placeholder. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/errors/error_resources.py | Adds Teams-specific error resource(s). |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/errors/init.py | Adds errors package exports + singleton. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/channel/init.py | Exports Channel route namespace. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/channel/route_handlers.py | Defines protocol for channel update handlers. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/channel/channel.py | Implements channel lifecycle/member route registration. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/team/init.py | Exports Team route namespace. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/team/route_handlers.py | Defines protocol for team update handlers. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/team/team.py | Implements team lifecycle route registration. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/message/init.py | Exports Message route namespace. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/message/route_handlers.py | Defines protocols for message read-receipt / actionable message handlers. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/message/message.py | Implements message update/actionable message route registration. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/task_module/init.py | Exports TaskModule route namespace. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/task_module/route_handlers.py | Defines protocols for task module fetch/submit handlers. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/task_module/task_module.py | Implements task module invoke route registration and request parsing. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/file_consent/init.py | Exports FileConsent route namespace. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/file_consent/route_handlers.py | Defines protocol for file consent handlers. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/file_consent/file_consent.py | Implements file consent invoke routing and response sending. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/config/init.py | Exports Config route namespace. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/config/route_handlers.py | Defines protocol for Teams config handlers. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/config/config.py | Implements config invoke routing and invoke-response sending. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/meeting/init.py | Exports Meeting route namespace. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/meeting/route_handlers.py | Defines protocols for meeting event handlers. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/meeting/meeting.py | Implements meeting lifecycle and participant event routing. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/message_extension/init.py | Exports MessageExtension route namespace. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/message_extension/route_handlers.py | Defines protocols for composeExtension handlers. |
| libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/message_extension/message_extension.py | Implements composeExtension invoke routing and payload parsing. |
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/turn_context.py | Tightens _activity typing and makes send_activity always return a ResourceResponse. |
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/authorization.py | Refactors naming toward connections and adds a connections accessor. |
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/app_options.py | Adds an import related to authorization connection typing. |
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/agent_application.py | Introduces HandoffHandler protocol use and adjusts _auth typing. |
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/_type_defs.py | Adds HandoffHandler protocol definition. |
| libraries/microsoft-agents-activity/microsoft_agents/activity/entity/entity_types.py | Registers ACTIVITY_TREATMENT in the known entity types enum. |
| libraries/microsoft-agents-activity/microsoft_agents/activity/entity/activity_treatment.py | Adds the new ActivityTreatment entity and ActivityTreatmentTypes enum. |
| libraries/microsoft-agents-activity/microsoft_agents/activity/entity/init.py | Exports the new treatment entity/types. |
| libraries/microsoft-agents-activity/microsoft_agents/activity/init.py | Exports the new treatment entity/types at the top level. |
Comments suppressed due to low confidence (2)
libraries/microsoft-agents-hosting-msteams/readme.md:108
- The README still contains unresolved git merge conflict markers (<<<<<<< / ======= / >>>>>>>), which will render incorrectly on PyPI/GitHub and indicates the merge wasn’t completed. Resolve the conflict and keep the correct package row(s).
libraries/microsoft-agents-hosting-msteams/pyproject.toml:8 - The project metadata renames this distribution to
microsoft-agents-hosting-msteams. The repo CI currently installs amicrosoft_agents_hosting_teams*.whlartifact for Python 3.12+; that will no longer exist after this rename unless CI and downstream references are updated.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| """Register a handler for Teams team event conversation update events.""" | ||
| decorator = self._create_decorator( | ||
| r"channel.*", auth_handlers=auth_handlers, rank=rank | ||
| ) | ||
| if handler is not None: |
| """Register a handler for Teams team event conversation update events.""" | ||
| decorator = self._create_decorator( | ||
| r"team.*", auth_handlers=auth_handlers, rank=rank | ||
| ) | ||
| if handler is not None: | ||
| return decorator(handler) | ||
| return decorator |
| def set_teams_api_client( | ||
| context: TurnContext, | ||
| connection_manager: Connections | ||
| ) -> None: | ||
| """ |
|
|
||
|
|
||
| class ActivityTreatment(Entity): | ||
| """Activity treatment information (entity type: "activity_treatment"). |
| return self._connections | ||
|
|
||
| @property | ||
| def connection_manager(self) -> Connections: |
| if is_supported_version: | ||
| from microsoft_agents.hosting.teams import TeamsAgentExtension | ||
|
|
| from microsoft_agents.hosting.teams import TeamsAgentExtension, TeamsInfo | ||
| from microsoft_agents.hosting.teams.teams_turn_context import TeamsTurnContext | ||
|
|
| dependencies = [ | ||
| "microsoft-agents-activity", | ||
| "microsoft-agents-hosting-core", | ||
| "microsoft-agents-authentication-msal", | ||
| "microsoft-agents-hosting-aiohttp", | ||
| "microsoft-agents-hosting-teams", | ||
| "python-dotenv", | ||
| "aiohttp", | ||
| ] |
| from microsoft_agents.hosting.core.app.oauth import AuthHandler | ||
| from microsoft_agents.hosting.core.authorization import Connections | ||
| from microsoft_agents.hosting.core.storage import Storage |
| class MessageExtension(Generic[StateT]): | ||
| """ | ||
| Route registration for Teams Message Extension (composeExtension) invoke activities. | ||
| Access via TeamsAgentExtension.message_extension. | ||
| """ |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 68 out of 73 changed files in this pull request and generated 19 comments.
Comments suppressed due to low confidence (1)
libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/authorization.py:142
connection_managerproperty returnsself._connection_manager, but the attribute was renamed to_connectionsearlier in this refactor. This will raiseAttributeErrorthe first time anything callsAuthorization.connection_manager(e.g.,AgentApplicationinitialization).
@property
def connection_manager(self) -> Connections:
"""
The connection manager for the authorization instance.
The connection manager is responsible for managing the connections to the various authentication providers.
:return: The connection manager.
:rtype: :class:`microsoft_agents.hosting.core.authorization.Connections`
"""
return self._connection_manager
| @property | ||
| def activity(self) -> TeamsActivity: | ||
| """Get the Teams activity for the turn context.""" | ||
| return TeamsActivity(self._activity) | ||
|
|
| @staticmethod | ||
| def get_selected_channel_id(self, activity: Activity) -> str | None: | ||
| """Get the ID of the selected channel from the activity, if it exists.""" | ||
| channel_data = _get_channel_data(activity) | ||
| if ( |
| @staticmethod | ||
| def enable_feedback_loop( | ||
| activity: Activity, feedback_loop_type: Literal["default", "custom"] = "default" | ||
| ) -> bool: | ||
|
|
||
| channel_data = _get_channel_data(activity) | ||
| if channel_data is not None: | ||
| return False | ||
|
|
||
| activity.channel_data = ChannelData( | ||
| feedback_loop=FeedbackLoop(type=feedback_loop_type) | ||
| ) | ||
| return True |
| async def authenticate_request( | ||
| self, | ||
| request: RequestInformation, | ||
| additional_authentication_context: dict[str, Any] = {}, | ||
| ) -> None: |
| if is_supported_version: | ||
| from microsoft_teams.api.models import FileConsentCardResponse | ||
| from microsoft_agents.hosting.teams import TeamsAgentExtension | ||
|
|
||
| _PATCH = ( | ||
| "microsoft_agents.hosting.teams.file_consent.file_consent._send_invoke_response" | ||
| ) | ||
|
|
| if is_supported_version: | ||
| from microsoft_agents.hosting.teams import TeamsAgentExtension | ||
|
|
||
| _PATCH = "microsoft_agents.hosting.teams.config.config._send_invoke_response" | ||
|
|
| if is_supported_version: | ||
| from microsoft_agents.hosting.teams import TeamsAgentExtension | ||
|
|
| from microsoft_agents.hosting.teams import TeamsAgentExtension, TeamsInfo | ||
| from microsoft_agents.hosting.teams.teams_turn_context import TeamsTurnContext |
| @@ -0,0 +1,100 @@ | |||
| """Internal utility helpers for the Teams hosting layer.""" | |||
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 68 out of 73 changed files in this pull request and generated 8 comments.
Comments suppressed due to low confidence (1)
libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/authorization.py:142
- Authorization.connection_manager now returns self._connection_manager, but the instance variable was renamed to _connections in this PR. Accessing .connection_manager will raise AttributeError at runtime (and breaks backward-compatible aliasing).
@property
def connection_manager(self) -> Connections:
"""
The connection manager for the authorization instance.
The connection manager is responsible for managing the connections to the various authentication providers.
:return: The connection manager.
:rtype: :class:`microsoft_agents.hosting.core.authorization.Connections`
"""
return self._connection_manager
| channel_data = self._get_channel_data() | ||
| if channel_data is not None: | ||
| return False | ||
|
|
||
| self.channel_data = ChannelData( | ||
| feedback_loop=FeedbackLoop(type=feedback_loop_type) | ||
| ) | ||
| return True |
| auth_handlers: Optional[list[str]] = None, | ||
| rank: RouteRank = RouteRank.DEFAULT, | ||
| ) -> ChannelUpdateHandler[StateT] | _RouteDecorator[ChannelUpdateHandler[StateT]]: | ||
| """Register a handler for Teams team event conversation update events.""" |
|
|
||
| class _SDKAuthenticationProvider(AuthenticationProvider): | ||
|
|
||
| def __init__(self, app: AgentApplication, context: TurnContext, handler_name: str): |
|
|
||
| import re | ||
| import pytest | ||
| from unittest.mock import AsyncMock, MagicMock |
| dependencies = [ | ||
| "microsoft-agents-activity", | ||
| "microsoft-agents-hosting-core", | ||
| "microsoft-agents-authentication-msal", | ||
| "microsoft-agents-hosting-aiohttp", | ||
| "microsoft-agents-hosting-teams", | ||
| "python-dotenv", | ||
| "aiohttp", | ||
| ] |
| from microsoft_agents.hosting.teams import TeamsAgentExtension, TeamsInfo | ||
| from microsoft_agents.hosting.teams.teams_turn_context import TeamsTurnContext |
| app["agent_app"] = agent_application | ||
| app["adapter"] = agent_application.adapter | ||
|
|
||
| run_app(app, host="localhost", port=int(environ.get("PORT", 3978))) |
|
|
||
| self._set_teams_activity() | ||
|
|
||
| _set_teams_api_client(context, app.connection_manager) |
|
|
||
| self._set_teams_activity() | ||
|
|
||
| _set_teams_api_client(context, app.connection_manager) |
| channel_data = self._get_channel_data() | ||
| if channel_data is not None: | ||
| return False | ||
|
|
||
| self.channel_data = ChannelData( | ||
| feedback_loop=FeedbackLoop(type=feedback_loop_type) | ||
| ) | ||
| return True |
|
|
||
|
|
||
| class ActivityTreatment(Entity): | ||
| """Activity treatment information (entity type: "activity_treatment"). |
| """Internal utility helpers for the Teams hosting layer.""" | ||
|
|
| ) | ||
| from ._utils import _try_get_channel_data | ||
|
|
||
| from .teams_activity import TeamsActivity |
| app["agent_app"] = agent_application | ||
| app["adapter"] = agent_application.adapter | ||
|
|
||
| run_app(app, host="localhost", port=int(environ.get("PORT", 3978))) |
| "microsoft-agents-hosting-core", | ||
| "microsoft-agents-authentication-msal", | ||
| "microsoft-agents-hosting-aiohttp", | ||
| "microsoft-agents-hosting-teams", |
| from microsoft_agents.hosting.teams import TeamsAgentExtension, TeamsInfo | ||
| from microsoft_agents.hosting.teams.teams_turn_context import TeamsTurnContext |
| def __call__( | ||
| self, | ||
| context: TeamsTurnContext, | ||
| state: _StateContra, | ||
| request: TaskModuleRequest, | ||
| /, | ||
| ) -> Awaitable[TaskModuleResponse]: | ||
| """Handle a task module fetch invoke. |
| def __call__( | ||
| self, | ||
| context: TeamsTurnContext, | ||
| state: _StateContra, | ||
| config_data: Any, | ||
| /, | ||
| ) -> Awaitable[ConfigResponse]: |
This pull request introduces several new features and improvements across the Microsoft Agents libraries, focusing on extensibility, type safety, and support for Microsoft Teams integration.
Key highlights:
microsoft_agents.hosting.msteamspackage, including utility helpers and a central extension class.ActivityTreatmententity and associated types to the activity model.TurnContextclass for better initialization and stricter type enforcement.Microsoft Teams Integration
microsoft_agents.hosting.msteamspackage, includingTeamsAgentExtension, Teams-specific entities, and utility helpers for handling Teams activities and responses. This provides a foundation for building Teams bots and agents. (libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/__init__.py[1]libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/_utils.py[2]libraries/microsoft-agents-hosting-msteams/microsoft_agents/hosting/msteams/channel/__init__.py[3]Activity Model Extensions
ActivityTreatmententity andActivityTreatmentTypesenum to the activity model, updating all relevant__init__.pyfiles and theEntityTypesenum to register the new entity type. (libraries/microsoft-agents-activity/microsoft_agents/activity/entity/activity_treatment.py[1]libraries/microsoft-agents-activity/microsoft_agents/activity/entity/__init__.py[2] [3]libraries/microsoft-agents-activity/microsoft_agents/activity/entity/entity_types.py[4]libraries/microsoft-agents-activity/microsoft_agents/activity/__init__.py[5] [6]Handler and Authorization Improvements
Added the
HandoffHandlerprotocol for improved type safety and consistency in handler registration, and refactored thehandoffmethod and related overloads to use this new protocol. (libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/_type_defs.py[1]libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/agent_application.py[2] [3] [4] [5] [6] [7]Refactored the
Authorizationclass to consistently use aconnectionsproperty, improving naming and providing a new property accessor for clarity. (libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/authorization.py[1] [2] [3] [4] [5]TurnContext and Activity Handling
TurnContextinitialization by making the_activityattribute explicit and enforcing stricter type checks. Also, updatedsend_activityto always return aResourceResponsefor consistency. (libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/turn_context.py[1] [2] [3] [4] [5]These changes collectively enhance the SDK's extensibility, reliability, and support for Microsoft Teams scenarios.