Problem
We want users to quickly tell us whether a Concierge agent response was helpful, directly in chat. Design is finalized β see the mocks in the parent issue https://github.com/Expensify/Expensify/issues/652178.
This issue covers the frontend only. The backend (capturing the feedback signal and posting the agent's thread replies) is already handled in Auth + Web-Expensify, so no new API work is required here.
Solution
Under each Concierge agent response, show a lightweight inline prompt:
Was that response useful? π π
- User taps π β add a
π emoji reaction to that message. The prompt disappears. Nothing else happens.
- User taps π β add a
π emoji reaction to that message. The prompt disappears. The backend then posts a Concierge reply in a thread on that message ("Please let us know what we can improve."), so the message's "N Replies" thread indicator appears. The user opens the thread and types what could be improved; the backend posts a short acknowledgement.
The π/π are real emoji reactions β after tapping, the standard reaction pill (e.g. π 1) shows on the message, exactly like any other reaction. The prompt should not reappear once the current user has reacted π/π to that response (it stays resolved across reloads). The agent's thread replies are posted by the backend and arrive via the normal Onyx/Pusher sync β the frontend does not author them.
Technical guidance (pointers, not prescriptive)
- Where to render: add the prompt in
src/pages/inbox/report/actionContents/ChatMessageContent.tsx as a sibling right after ReportActionItemMessage (next to the existing ChatActionableButtons). Reuse src/components/ReportActionItem/ActionableItemButtons.tsx.
- When to show it (gating): only for a Concierge agent reply β the report is a Concierge chat (
ReportUtils.isConciergeChatReport, actor CONST.ACCOUNT_ID.CONCIERGE); the action is an actual agent response (its originalMessage carries agentZeroRequestID and/or agentZero); and the current user has not already reacted π/π to it.
- Adding the reaction: call
toggleEmojiReaction(...) from src/libs/actions/EmojiReactions.ts with the emoji object from EmojiUtils.findEmojiByName('+1') (π) / findEmojiByName('-1') (π).
- Hiding after answer: check
EmojiUtils.hasAccountIDEmojiReacted(currentUserAccountID, ...) so it stays resolved across reloads.
- Thread indicator (
ReportActionItemThread) renders automatically once the backend posts the reply. (Open question for design: should tapping π also auto-open the thread, or just leave the indicator for the user to tap?)
Out of scope
- Any feedback storage or new API β the backend owns capturing the signal.
- The agent's thread replies ("Please let us knowβ¦" / the acknowledgement) β posted by the backend.
- Custom
@expensify.ai agents β this pass is Concierge only.
Acceptance criteria
References
Problem
We want users to quickly tell us whether a Concierge agent response was helpful, directly in chat. Design is finalized β see the mocks in the parent issue https://github.com/Expensify/Expensify/issues/652178.
This issue covers the frontend only. The backend (capturing the feedback signal and posting the agent's thread replies) is already handled in Auth + Web-Expensify, so no new API work is required here.
Solution
Under each Concierge agent response, show a lightweight inline prompt:
πemoji reaction to that message. The prompt disappears. Nothing else happens.πemoji reaction to that message. The prompt disappears. The backend then posts a Concierge reply in a thread on that message ("Please let us know what we can improve."), so the message's "N Replies" thread indicator appears. The user opens the thread and types what could be improved; the backend posts a short acknowledgement.The π/π are real emoji reactions β after tapping, the standard reaction pill (e.g.
π 1) shows on the message, exactly like any other reaction. The prompt should not reappear once the current user has reacted π/π to that response (it stays resolved across reloads). The agent's thread replies are posted by the backend and arrive via the normal Onyx/Pusher sync β the frontend does not author them.Technical guidance (pointers, not prescriptive)
src/pages/inbox/report/actionContents/ChatMessageContent.tsxas a sibling right afterReportActionItemMessage(next to the existingChatActionableButtons). Reusesrc/components/ReportActionItem/ActionableItemButtons.tsx.ReportUtils.isConciergeChatReport, actorCONST.ACCOUNT_ID.CONCIERGE); the action is an actual agent response (itsoriginalMessagecarriesagentZeroRequestIDand/oragentZero); and the current user has not already reacted π/π to it.toggleEmojiReaction(...)fromsrc/libs/actions/EmojiReactions.tswith the emoji object fromEmojiUtils.findEmojiByName('+1')(π) /findEmojiByName('-1')(π).EmojiUtils.hasAccountIDEmojiReacted(currentUserAccountID, ...)so it stays resolved across reloads.ReportActionItemThread) renders automatically once the backend posts the reply. (Open question for design: should tapping π also auto-open the thread, or just leave the indicator for the user to tap?)Out of scope
@expensify.aiagents β this pass is Concierge only.Acceptance criteria
References