Skip to content

feat/bug: add custom feedback form & fix pydantic valid error on MessageUpdateActivity#349

Merged
lilyydu merged 8 commits into
mainfrom
lilyydu/bugs
Apr 3, 2026
Merged

feat/bug: add custom feedback form & fix pydantic valid error on MessageUpdateActivity#349
lilyydu merged 8 commits into
mainfrom
lilyydu/bugs

Conversation

@lilyydu

@lilyydu lilyydu commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

resolves: #326 and #347

  • added default empty string for text in MessageUpdateActivity (otherwise throws pydantic error)
  • added support for custom feedback form (through ChannelData.feedback_loop).

Custom Feedback Context:
Learn Doc

  • previously we had a flag called enable_feedback_loop which only enables the default feedback form
  • now, we have a param called feedback_loop that can either be default or custom.
  • however, the service doesn't accept both at once. Hence I normalized enable_feedback_loop into feedback_loop. whenever enable_feedback_loop is set to True, it'll set feedback_loop to default and itself back to None.
image

Example Usage:

@app.on_message
async def on_message(ctx: ActivityContext[MessageActivity]):
    if ctx.activity.text == "feedback default":
    # This is the legacy approach that normalizes. Recommended to use `feedback_loop` instead.
        await ctx.send(
            MessageActivityInput(text="Rate this response!").with_channel_data(ChannelData(feedback_loop_enabled=True))
        )
    elif ctx.activity.text == "feedback custom":
        await ctx.send(
            MessageActivityInput(text="Rate this response!").add_feedback(
                mode="custom"
            )  # triggers message/fetchTask invoke
        )


@app.on_message_fetch_task
async def on_feedback_fetch_task(ctx: ActivityContext[MessageFetchTaskInvokeActivity]):
    card = AdaptiveCard.model_validate(
        {
            "type": "AdaptiveCard",
            "version": "1.4",
            "body": [
                {"type": "TextBlock", "text": "Tell us more about your feedback:"},
                {
                    "type": "Input.Text",
                    "id": "feedbackText",
                    "placeholder": "Enter your feedback here...",
                    "isMultiline": True,
                },
            ],
            "actions": [
                {"type": "Action.Submit", "title": "Submit"},
            ],
        }
    )
    return TaskModuleInvokeResponse(
        task=TaskModuleContinueResponse(
            value=CardTaskModuleTaskInfo(
                title="Feedback",
                card=card_attachment(AdaptiveCardAttachment(content=card)),
            )
        )
    )

Copilot AI review requested due to automatic review settings April 2, 2026 22:31

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

Adds SDK support for Teams “custom feedback form” flows (message/fetchTask) and fixes a Pydantic validation failure when messageUpdate activities omit text (e.g., attachment-only updates).

Changes:

  • Add MessageFetchTaskInvokeActivity + apps routing hooks (on_message_fetch_task) for custom feedback task modules.
  • Introduce ChannelData.feedback_loop / FeedbackLoop and update Activity.add_feedback() to support "default" vs "custom".
  • Default MessageUpdateActivity.text to "" and add unit tests to prevent regressions.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/apps/src/microsoft_teams/apps/routing/generated_handlers.py Adds generated handler registration method for message.fetch-task.
packages/apps/src/microsoft_teams/apps/routing/activity_route_configs.py Registers new route config for message/fetchTask invokes returning a task module response.
packages/api/tests/unit/test_message_activities.py Adds tests ensuring MessageUpdateActivity.text defaults to empty string and inbound parsing succeeds without text.
packages/api/tests/unit/test_activity.py Updates feedback tests for new feedback_loop model and adds custom-mode assertion.
packages/api/src/microsoft_teams/api/models/channel_data/feedback_loop.py New FeedbackLoop model representing feedback configuration.
packages/api/src/microsoft_teams/api/models/channel_data/channel_data.py Adds feedback_loop field and normalization logic for legacy feedback_loop_enabled.
packages/api/src/microsoft_teams/api/models/channel_data/init.py Exports FeedbackLoop from the channel_data package.
packages/api/src/microsoft_teams/api/models/activity.py Extends add_feedback() to support "default" vs "custom" via feedback_loop.
packages/api/src/microsoft_teams/api/activities/message/message_update.py Defaults MessageUpdateActivity.text to "" to avoid validation errors.
packages/api/src/microsoft_teams/api/activities/invoke/message/fetch_task.py New invoke activity model for message/fetchTask.
packages/api/src/microsoft_teams/api/activities/invoke/message/init.py Re-exports newly added message invoke models.
packages/api/src/microsoft_teams/api/activities/invoke/init.py Adds MessageFetchTaskInvokeActivity to the invoke tagged union.

Comment thread packages/api/src/microsoft_teams/api/models/channel_data/channel_data.py Outdated
Comment thread packages/api/src/microsoft_teams/api/models/channel_data/feedback_loop.py Outdated
Comment thread packages/apps/tests/test_feedback_routing.py Outdated
@corinagum

corinagum commented Apr 3, 2026

Copy link
Copy Markdown
Contributor
image

Do you happen to know why learn docs specify Bot Framework SDK here? Seems odd...

Oh I guess they just meant using the Bot Framework SDK. The placement is just a little weird because it's modifying the data object. Please disregard.

Would we be able to get Ricky's help to update the docs with Teams SDK info?

@corinagum corinagum 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.

lgtm!
Do you know if there's a plan to deprecate feedbackLoopEnabled? Do we want to plan to deprecate it for simplicity?

@lilyydu

lilyydu commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator Author
image ~Do you happen to know why learn docs specify Bot Framework SDK here? Seems odd...~

Oh I guess they just meant using the Bot Framework SDK. The placement is just a little weird because it's modifying the data object. Please disregard.

Would we be able to get Ricky's help to update the docs with Teams SDK info?

yep! We should be able to get Ricky to help us update

lgtm! Do you know if there's a plan to deprecate feedbackLoopEnabled? Do we want to plan to deprecate it for simplicity?

afaik from the docs it seems to be in public developer preview still! Once it's officially GA'd, I think we can begin the effort to deprecate

@heyitsaamir heyitsaamir left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we show an example?

Comment thread packages/api/src/microsoft_teams/api/models/activity.py
@lilyydu
lilyydu merged commit 3ece4ba into main Apr 3, 2026
7 checks passed
@lilyydu
lilyydu deleted the lilyydu/bugs branch April 3, 2026 22:01
lilyydu added a commit to microsoft/teams.ts that referenced this pull request Apr 21, 2026
Custom Feedback Context:
[Learn
Doc](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bot-messages-ai-generated-content?tabs=desktop%2Cjs%2Cbotmessage#feedback-buttons)

- previously we had a flag called `feedbackLoopEnabled` which only
enables the default feedback form
- now, we have a param called `feedbackLoop` that can either be default
or custom.
- updated AI sample to feature the custom feedback loop
- also included the normalization to `feedbackLoop` when using
`withChannelData..`
- py equivalent: microsoft/teams.py#349

---------

Co-authored-by: lilydu <[email protected]>
lilyydu added a commit to microsoft/teams.net that referenced this pull request Apr 22, 2026
Custom Feedback Context:
[Learn
Doc](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bot-messages-ai-generated-content?tabs=desktop%2Cjs%2Cbotmessage#feedback-buttons)

- previously we had a flag called feedbackLoopEnabled which only enables
the default feedback form
- now, we have a param called feedbackLoop that can either be default or
custom.
- updated AI sample to feature the custom feedback loop
- also included the normalization to feedbackLoop when using
withChannelData..
- py equivalent: microsoft/teams.py#349
- ts equivalent: microsoft/teams.ts#522

---------

Co-authored-by: lilydu <[email protected]>
Co-authored-by: Copilot <[email protected]>
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.

[Bug]: message/fetchTask is missing when using custom feedback forms

4 participants