Skip to content

Add follow-up question support to Slack request action#2399

Open
ravikiranvm wants to merge 2 commits into
mainfrom
add-follow-up-question-to-slack-request-action
Open

Add follow-up question support to Slack request action#2399
ravikiranvm wants to merge 2 commits into
mainfrom
add-follow-up-question-to-slack-request-action

Conversation

@ravikiranvm

@ravikiranvm ravikiranvm commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Part of OPS-4626

Extends the follow-up question capability shipped for Teams in #2398 to the Slack Request Action block: any action button can ask the person a question in the browser before the workflow resumes, and the workflow receives the typed answer.

What's new

Screenshot 2026-07-16 at 4 55 10 PM
  • The same three optional properties per action button as Teams: Follow-up question, Answer format (Text / Email / Number), and No answer option
  • The answer is surfaced in the step output as parameters.answer (all non-routing resume query params are exposed under parameters, mirroring the Teams block)
  • buildWrapperUrl moves from the Teams block to @openops/common so both blocks share one implementation (the Teams block now imports it from there; behavior unchanged)

The Slack-specific part

Slack runs in two modes, and the browser form works in both:

  • Non-interaction mode (SLACK_ENABLE_INTERACTIONS=false): buttons are already link buttons — a follow-up button opens collect_input.html instead of resume_execution.html.
  • Interactions mode (default): follow-up buttons get a url so Slack opens the form — but Slack still sends an interaction payload for link buttons, so the message metadata now carries followUpActions (the follow-up button texts) and /v1/slack/interactions skips resuming for those clicks, letting the browser form own the resume. The check lives in a small pure helper (is-follow-up-action.ts) with its own unit tests, plus endpoint-level integration tests asserting the resume webhook is not fired for follow-up clicks and still fires for normal ones.

Slack modals (views.open) were considered and deliberately not used: they require a bot token + trigger_id within 3 seconds, while the interactions endpoint is a credential-free relay (signature check + response_url only), and non-interaction mode would still need the browser form anyway. One codepath covers both modes.

Emoji normalization fix

Slack interaction payloads return button text in emoji-shortcode form (🎲 arrives as :game_die:), which is why message matching already normalizes via normalizeEmojiString. Button texts are now stored normalized in followUpActions and in the actionClicked resume param baked into link-button URLs — the latter fixes a latent bug where a unicode-emoji button in non-interaction mode never matched on resume and the flow hung until timeout.

Safety

  • Buttons without a follow-up question are untouched in both modes; messages sent by older block versions have no followUpActions metadata and behave exactly as before (covered by tests)
  • Prototype-pollution keys are excluded from parameters
  • Client-side validation is convenience only — consuming workflows should re-validate the answer server-side, since resume URLs are capability URLs

Testing Checklist

  • I tested the feature thoroughly, including edge cases
  • I verified all affected areas still work as expected
  • Automated tests were added/updated if necessary
  • Changes are backwards compatible with any existing data

Unit/integration: blocks-slack 99 tests, blocks-microsoft-teams 57, openops-common 460, server-api slack unit 19 — all passing; lint clean on all four projects.

Extends the follow-up question capability shipped for Teams (#2398) to the
Slack Request Action block. Buttons with a follow-up question become link
buttons opening the collect_input.html page in both interaction modes; the
interactions endpoint skips resuming for those clicks so the browser form
owns the resume, and the answer surfaces in the step output as
parameters.answer.

The shared buildWrapperUrl helper moves from the Teams block to
@openops/common so both blocks use one implementation. Button texts are
stored emoji-normalized in followUpActions and the actionClicked resume
param, fixing a latent emoji-button resume mismatch in non-interaction mode.

Part of OPS-4626.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 16, 2026 10:45
@linear

linear Bot commented Jul 16, 2026

Copy link
Copy Markdown

OPS-4626

Comment thread packages/blocks/slack/test/wait-for-interaction.test.ts Dismissed

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 extends the “follow-up question” flow (previously added for Teams) to the Slack Request Action block. It adds optional per-button follow-up question metadata, routes follow-up clicks through the browser-based collect_input.html form in both Slack interaction modes, and exposes typed answers back to workflows as parameters.answer (plus any other non-routing resume query params).

Changes:

  • Add follow-up question / answer format / no-answer option support to Slack request-action buttons, using collect_input.html to gather input before resuming.
  • Prevent /v1/slack/interactions from resuming executions for follow-up button clicks by checking message metadata (followUpActions) via a small helper with unit + integration tests.
  • Move buildWrapperUrl into @openops/common for shared Slack/Teams behavior and update imports/exports/tests accordingly.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/server/api/test/unit/slack/is-follow-up-action.test.ts Unit tests for follow-up action detection helper.
packages/server/api/test/integration/cloud/slack-integration/slack-interaction.test.ts Integration coverage ensuring follow-up clicks do not trigger resume, while normal clicks still do.
packages/server/api/src/app/slack/slack-interaction-module.ts Skips resume when the interaction corresponds to a follow-up action.
packages/server/api/src/app/slack/is-follow-up-action.ts New pure helper to decide whether an interaction is a follow-up action.
packages/openops/test/build-wrapper-url.test.ts Updates tests to the new buildWrapperUrl module location.
packages/openops/src/lib/build-wrapper-url.ts New shared wrapper URL builder supporting both resume and collect-input pages.
packages/openops/src/index.ts Exposes buildWrapperUrl from @openops/common.
packages/blocks/slack/test/wait-for-interaction.test.ts Updates expectations and adds tests for surfacing extra resume params as parameters (incl. pollution-key exclusions).
packages/blocks/slack/test/wait-for-action.test.ts Updates action result expectations to include parameters.
packages/blocks/slack/test/request-action-message.test.ts Adds coverage for follow-up buttons, wrapper URLs, followUpActions metadata, and emoji normalization.
packages/blocks/slack/src/lib/common/wait-for-interaction.ts Adds parameters to output, derived from resume query params excluding routing/pollution keys.
packages/blocks/slack/src/lib/common/props.ts Adds new optional follow-up-related button properties to Slack Request Action UI.
packages/blocks/slack/src/lib/actions/request-action-message.ts Generates follow-up wrapper URLs, stores normalized followUpActions, and normalizes button text for resume matching.
packages/blocks/microsoft-teams/src/lib/actions/request-action-message.ts Switches to importing shared buildWrapperUrl from @openops/common.

@ravikiranvm
ravikiranvm requested a review from MarceloRGonc July 16, 2026 11:31
@sonarqubecloud

Copy link
Copy Markdown

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.

3 participants