Today /storytime is the only way to start a story. This adds a second
entry point: mentioning the bot in a channel starts one.
@Storytime Bot
@Storytime Bot -t Pirates -t Space
@Storytime Bot --video --style claymationApproach
A mention arrives as an app_mention event on the existing
/api/slack/webhook endpoint, which already handles the Events API. Unlike a
slash command it carries no trigger_id, so the configuration modal cannot be
opened from one. The mention therefore starts the story directly: the bot's own
mention is stripped out of the text and the remainder is parsed with
parseStorytimeArgs, the same flags the slash command accepts, with the usual
defaults for anything left out. Other words in the message land in arg's
positional bucket and are ignored, so @Storytime Bot let's write something
starts a story with the defaults.
Only the bot's own mention is removed, identified from authorizations[0].user_id,
so -t "a tale for <@U999>" keeps the other user intact. Without
authorizations, every user mention is dropped instead.
Existing behavior is untouched: the slash command still opens the modal, the modal still starts the story on submit, and thread replies still resume the story hook.
Guards
- Mentions inside a thread do not start a story. Replies in a story thread
already continue that story through the
messageevent; starting here would spawn a second story in the channel while the first is still running. Only top-level mentions (nothread_ts, orthread_ts === ts) start one. - Redelivered events are ignored. Slack retries when it doesn't see a 200
within three seconds, which a cold start can hit even though the handler ran.
A mention carrying
x-slack-retry-numis skipped rather than starting a duplicate story. - Mentions posted by a bot are ignored, the same way thread messages from bots already are.
- Gateway transcripts stay off, matching the slash command, whose modal
leaves the field out — without this,
@Storytime Bot --transcriptswould be the one way to turn them on from Slack, contradicting the README.
The story starts inside waitUntil so Slack gets its acknowledgement
immediately. Invalid flags and start failures are reported to the mentioning
user with an ephemeral message, matching the slash command and modal paths.
Slack app configuration
Mention handling needs the app_mentions:read scope and the app_mention
event subscription on the same Request URL the message.channels subscription
already uses. Existing installations must add both and reinstall; until they
do, nothing changes for them. Both are documented in the README, along with the
new section describing the mention flow.
Tests
pnpm test: 159 passing, up from 135. New app/api/slack/webhook.test.ts
covers the mention path end to end through the route — defaults, flags,
surrounding chatter, each guard above, and the error paths — plus the
thread-reply hook resume, which had no coverage before. New
lib/slack-mention.test.ts covers mention stripping, including labeled
mentions, other users, and channel links. pnpm build, pnpm lint, and
tsc --noEmit are clean.
Not covered
Starting a story inside a thread. storytime() posts to a channel and has no
thread parameter, so that would be a larger change.
🤖 Generated with Claude Code
Activity
3Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
The latest updates on your projects. Learn more about Vercel for GitHub.