fix(api): gate Slack thread sessions on the flag and make quieting explicit

Merged
AV
2mo ago
+362-59

Follow-up to #7583 (thread sessions) from its first live test and review.

Summary

  • Flag gates the whole feature. The handler checks slack-thread-follow-ups once per delivery. Off: no session row, no thread memory, no quiet tool. Every non-Superset workspace runs the Phase 0 path exactly as before.
  • Slack ack no longer waits on PostHog. The flag is cached per team for 60s and bounded at 1s, failing closed. The events route pays for PostHog at most once a minute per team.
  • Quieting is explicit and reversible. The regex that muted a thread on any message containing "only respond … mention" is gone. !mute / !unmute are handled deterministically without running the agent. The model also gets a slack_thread_quiet tool (both directions) and its context states whether the thread is currently quiet, so "respond without being mentioned again" works.

Manual QA (Superset workspace, flag on)

  • @Superset !mute in a thread → "I'll stay out of this thread…"; a plain reply gets no answer; @Superset !unmute → replies answered again
  • @Superset only reply when I mention you → model calls the tool and confirms; @Superset go back to answering everything → model unmutes
  • @Superset build a bot that should only respond when mentioned → treated as a request, not a mute
  • A workspace without the flag: mention works, no slack_thread_sessions row is written

Testing

  • bun test src/app/api/integrations/slack (80 pass)
  • bunx tsc --noEmit --pretty false in apps/api (exit 0)
  • bunx biome check apps packages

Follow-ups

  • #7586 (follow-up queue) rebases onto this.

https://claude.ai/code/session_01YDDSQYG6WSZn4jXWTR3Pid


Summary by cubic

Gates Slack thread sessions (memory, quieting, follow-ups) behind the slack-thread-follow-ups flag and replaces keyword-based thread muting with explicit, reversible controls.

  • Teams without the flag keep the previous path untouched, and an unmentioned reply that was enqueued while the flag was on is dropped if the worker sees it off.
  • The Slack acknowledgement no longer waits on PostHog; the flag is cached per team for 60 seconds with a 1-second timeout that fails closed.
  • !mute/!quiet and !unmute/!unquiet are handled deterministically without running the agent, behind the delivery guard so redeliveries can't reapply a stale setting or post twice; in DMs they're ignored and the quiet tool is withheld.
  • The model gets a slack_thread_quiet tool, sees the thread's quiet state and the !mute/!unmute commands in its context, and can flip the state in either direction.

Summary by CodeRabbit

  • New Features

    • Added Slack thread commands to mute or unmute follow-up responses using !mute, !quiet, !unmute, or !unquiet.
    • The Slack agent can report and change a thread’s quiet state during a conversation.
  • Behavior Changes

    • Thread follow-up controls are enabled selectively and remain disabled when unavailable.
    • Queued follow-ups are dropped when follow-up handling is disabled.
    • Direct messages continue reaching the agent normally and are not muted by thread commands.
    • Ordinary messages that mention muting or quieting are treated as regular requests rather than commands.