Skip to content

feat: add workflow form submission via --field#74

Open
shhac wants to merge 1 commit intostablyai:mainfrom
shhac:paul/feat-workflow-fields
Open

feat: add workflow form submission via --field#74
shhac wants to merge 1 commit intostablyai:mainfrom
shhac:paul/feat-workflow-fields

Conversation

@shhac
Copy link
Copy Markdown
Contributor

@shhac shhac commented Mar 25, 2026

Summary

Adds --field support to workflow run, enabling form submission for workflows that present an interactive form after being triggered. This was called out as a follow-up in #40:

Form submission via --field (RTM WebSocket) will follow in a separate PR.

  • workflow run <trigger-id> --channel #ops --field "Title=My request" --field "Priority=High"
  • Without --field, behavior is unchanged (trip-only, as before)
  • Field titles are validated against the workflow schema before submission
  • Requires browser auth (xoxc/xoxd -- also from desktop app) — standard bot tokens can trip triggers but cannot interact with the modal form

Why WebSockets (RTM)

Slack's workflow forms use a view_opened event delivered over the RTM WebSocket to provide the modal's view_id and block structure. There is no REST endpoint that returns this — the view is pushed to the client asynchronously after the trigger is tripped. Without a WebSocket listener, there's no way to know the view_id or the block_id/action_id mappings needed to call views.submit.

I investigated alternatives (polling views.* endpoints, intercepting via response_urls) but Slack doesn't expose the view through any other channel. WebSocket is the only path.

Implementation

The WebSocket connection uses node:https request upgrade (Upgrade: websocket header) rather than the WebSocket global or a library. This approach works in Bun despite Bun's incomplete WebSocket client support for cookie-authenticated wss:// connections — the Node.js http.request upgrade path is fully supported. The trade-off is manually parsing WebSocket frames (RFC 6455), but server→client frames are unmasked so the parser is straightforward.

Flow

  1. rtm.connect → get WebSocket URL
  2. Open WebSocket, start listening for view_opened
  3. Trip the trigger (existing runWorkflow)
  4. Receive view_opened → extract view_id + block/action structure
  5. Map user-supplied --field values to the correct block_id/action_id pairs using the workflow schema
  6. views.submit with the assembled state

New files

  • src/lib/rtm-websocket.ts — short-lived RTM WebSocket connection with frame parser
  • src/slack/workflow-submit.ts — form validation, submission orchestration
  • test/rtm-websocket.test.ts — WebSocket frame parser unit tests
  • test/workflow-submit.test.ts — field validation + auth guard tests

Note

To my knowledge, no other Slack CLI tool supports workflow form submission — existing tools can only trip triggers. This fills a gap for automating workflows that require field input.

Test plan

  • Lint, typecheck clean
  • Unit tests for frame parser (all payload sizes, edge cases) and field validation
  • Manual: form submission verified against live workspace with multi-field workflow

@AmethystLiang
Copy link
Copy Markdown
Contributor

Thx for the PR as always! Will be able to look it over tmr :-D

@shhac shhac force-pushed the paul/feat-workflow-fields branch from 4dd76f8 to 508ce98 Compare April 15, 2026 20:16
Add `--field Title=value` support to `workflow run`, enabling form
submission through a short-lived RTM WebSocket that captures
view_opened events and submits via views.submit.

New modules:
- rtm-websocket: low-level Bun-compatible WebSocket over node:https
- workflow-submit: orchestrates trip → capture → submit flow
@shhac shhac force-pushed the paul/feat-workflow-fields branch from 508ce98 to ddccbad Compare May 2, 2026 14:48
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.

2 participants