Passing in missing arguments to TeamsActivityHandler method hooks#450
Conversation
There was a problem hiding this comment.
Pull request overview
This PR tightens the Microsoft Teams activity handling layer by validating incoming Teams invoke/event payloads into specific Pydantic models before dispatching to handler hooks, and by adjusting Teams member/conversation update dispatch so handler hooks receive the intended arguments consistently.
Changes:
- Validate various Teams invoke payloads (file consent, O365 connector actions, link queries, messaging extension actions/queries, tab fetch/submit, etc.) with Pydantic models before calling hook methods.
- Refactor Teams conversation update handling to pass additional context (e.g.,
channel_info/team_info) into Teams-specific hooks, and ensure generic member-added/removed hooks are invoked from the dispatchers. - Expand
TeamsChannelAccountto includeaad_object_idandrole, and refine invoke response typing in the core activity handler.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| libraries/microsoft-agents-hosting-teams/microsoft_agents/hosting/teams/teams_activity_handler.py | Adds Pydantic validation for Teams invoke/event payloads and refactors Teams dispatch/hook signatures. |
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/activity_handler.py | Tweaks _create_invoke_response typing and removes an unused import. |
| libraries/microsoft-agents-activity/microsoft_agents/activity/teams/teams_channel_account.py | Adds aad_object_id and role fields to the Teams channel account model. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
libraries/microsoft-agents-hosting-teams/microsoft_agents/hosting/teams/teams_activity_handler.py:176
model_validate(...)calls above can raise PydanticValidationErrorfor malformed/empty invoke payloads, but the currentexceptblock only maps custom Teams exceptions. That means a bad client payload can surface as an unhandled exception (likely 500) instead of returning a 400.
Consider mapping Pydantic validation errors to HTTPStatus.BAD_REQUEST here.
except Exception as err:
if str(err) == str(teams_errors.TeamsNotImplemented):
return InvokeResponse(status=int(HTTPStatus.NOT_IMPLEMENTED))
elif str(err) == str(teams_errors.TeamsBadRequest):
return InvokeResponse(status=int(HTTPStatus.BAD_REQUEST))
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…ft/Agents-for-python into users/robrandao/teams-ah
| if turn_context.activity.channel_id == "msteams": | ||
| channel_data = ( | ||
| TeamsChannelData.model_validate(turn_context.activity.channel_data) | ||
| if turn_context.activity.channel_data | ||
| else None | ||
| channel_data = TeamsChannelData.model_validate( | ||
| turn_context.activity.channel_data | ||
| ) |
| elif name == "fileConsent/invoke": | ||
| card_response = FileConsentCardResponse.model_validate(value) | ||
| return self._create_invoke_response( | ||
| await self.on_teams_file_consent(turn_context, value) | ||
| await self.on_teams_file_consent(turn_context, card_response) | ||
| ) | ||
| elif name == "actionableMessage/executeAction": | ||
| await self.on_teams_o365_connector_card_action(turn_context, value) | ||
| query = O365ConnectorCardActionQuery.model_validate(value) | ||
| await self.on_teams_o365_connector_card_action(turn_context, query) |
| elif name == "composeExtension/submitAction": | ||
| action = MessagingExtensionAction.model_validate(value) | ||
| return self._create_invoke_response( | ||
| await self.on_teams_messaging_extension_submit_action_dispatch( | ||
| turn_context, value | ||
| turn_context, action | ||
| ) | ||
| ) | ||
| elif name == "composeExtension/fetchTask": | ||
| action = MessagingExtensionAction.model_validate(value) | ||
| return self._create_invoke_response( | ||
| await self.on_teams_messaging_extension_fetch_task( | ||
| turn_context, value | ||
| turn_context, action | ||
| ) | ||
| ) | ||
| elif name == "composeExtension/querySettingUrl": | ||
| query = MessagingExtensionQuery.model_validate(value) | ||
| return self._create_invoke_response( |
| elif name == "tab/fetch": | ||
| tab_request = TabRequest.model_validate(value) | ||
| return self._create_invoke_response( | ||
| await self.on_teams_tab_fetch(turn_context, value) | ||
| await self.on_teams_tab_fetch(turn_context, tab_request) | ||
| ) | ||
| elif name == "tab/submit": | ||
| tab_submit = TabSubmit.model_validate(value) | ||
| return self._create_invoke_response( | ||
| await self.on_teams_tab_submit(turn_context, value) | ||
| await self.on_teams_tab_submit(turn_context, tab_submit) | ||
| ) |
| if turn_context.activity.channel_id == "msteams": | ||
| if turn_context.activity.name == "application/vnd.microsoft.readReceipt": | ||
| return await self.on_teams_read_receipt(turn_context) | ||
| return await self.on_teams_read_receipt( | ||
| ReadReceiptInfo.model_validate(turn_context.activity.value), | ||
| turn_context, | ||
| ) |
| if turn_context.activity.channel_id == "msteams": | ||
| channel_data = ( | ||
| TeamsChannelData.model_validate(turn_context.activity.channel_data) | ||
| if turn_context.activity.channel_data | ||
| else None | ||
| channel_data = TeamsChannelData.model_validate( | ||
| turn_context.activity.channel_data | ||
| ) | ||
|
|
| elif name == "fileConsent/invoke": | ||
| card_response = FileConsentCardResponse.model_validate(value) | ||
| return self._create_invoke_response( | ||
| await self.on_teams_file_consent(turn_context, value) | ||
| await self.on_teams_file_consent(turn_context, card_response) | ||
| ) |
This pull request introduces several improvements to the Teams activity handling logic, focusing on stricter type validation, enhanced event dispatching, and improved handling of Teams-specific activities. The most significant changes involve validating incoming payloads with Pydantic models, refactoring event and member dispatch methods for clarity and correctness, and expanding the
TeamsChannelAccountmodel to support more fields.Type validation and payload handling improvements:
Teams member and conversation update handling:
_get_list_team_membersto convert a list ofChannelAccountobjects toTeamsChannelAccountobjects, centralizing and simplifying this conversion logic.Model enhancements:
TeamsChannelAccountmodel to includeaad_object_idandrolefields, allowing for richer representation of Teams user accounts.Minor code improvements:
_create_invoke_responsemethod signature for better type hinting and optional argument handling.activity_handler.py.