Handling Events
Register normalized event handlers for mentions, messages, reactions, actions, and slash commands.
ChatSDK normalizes events from all platforms into a consistent set of callbacks. Register handlers on your Chat instance before mounting webhooks.
on_new_mention
Fires when someone @-mentions your bot. This is the most common handler.
bot.on_new_mention do |thread, message|
# thread - ChatSDK::Thread (reply here)
# message - ChatSDK::Message (the incoming message)
thread.post("You said: #{message.text}")
endThe message object provides:
message.text-- The message textmessage.author-- AChatSDK::Authorwithid,name,platform,bot?message.id-- Platform-specific message IDmessage.thread_id-- Thread identifiermessage.channel_id-- Channel identifiermessage.raw-- The raw platform payload (for escape-hatch access)
on_new_message(pattern)
Matches mentions whose text matches a Regexp pattern.
bot.on_new_message(/deploy (\w+)/) do |thread, message|
match = message.text.match(/deploy (\w+)/)
thread.post("Deploying #{match[1]}...")
endOnly mention events whose message.text matches the regex will trigger this handler. This is useful for building command-style bots.
on_subscribed_message
Fires when a new message arrives in a thread your bot has subscribed to. Use thread.subscribe inside another handler to opt in.
bot.on_new_mention do |thread, message|
thread.post("I'm listening to this thread now.")
thread.subscribe
end
bot.on_subscribed_message do |thread, message|
# Called for every subsequent message in subscribed threads
thread.post("Got it: #{message.text}")
endCall thread.unsubscribe to stop receiving messages, or check thread.subscribed?.
on_direct_message
Fires when a user sends your bot a direct message (not in a channel).
bot.on_direct_message do |thread, message|
thread.post("This is a private conversation with #{message.author.name}.")
endon_reaction
Fires when a user adds or removes an emoji reaction. The block receives an event object.
# Handle all reactions
bot.on_reaction do |event|
# event.emoji - String, e.g. "thumbsup"
# event.user_id - Who reacted
# event.message_id - The message that was reacted to
# event.added? - true if added, false if removed
# event.removed? - opposite of added?
# event.thread - ChatSDK::Thread for replying
if event.added?
event.thread.post("Thanks for the :#{event.emoji}:!")
end
end
# Filter to specific emojis (pass an Array)
bot.on_reaction(%w[thumbsup heart]) do |event|
event.thread.post("Positive vibes!")
endon_action
Fires when a user clicks a button or interacts with a select menu in a card. Match by action_id.
bot.on_action("approve_btn") do |event|
# event.action_id - "approve_btn"
# event.value - The value attached to the button/option
# event.user - ChatSDK::Author
# event.trigger_id - For opening modals
# event.thread - ChatSDK::Thread
event.thread.post("Approved by #{event.user.name}!")
endSee Actions for more examples, and Cards for how to define buttons.
on_slash_command
Fires when a user types a slash command (e.g., /deploy).
bot.on_slash_command("/deploy") do |event|
# event.command - "/deploy"
# event.text - Everything after the command
# event.user_id - Who ran the command
# event.channel_id - Where it was run
# event.trigger_id - For opening modals
# event.thread - ChatSDK::Thread
event.thread.post("Deploying: #{event.text}")
endSlack assistant, App Home and membership events
Slack assistant thread, Home tab, and channel membership events are available through event-object handlers:
slack = bot.adapter(:slack)
bot.on_assistant_thread_started do |event|
slack.set_suggested_prompts(
channel_id: event.channel_id,
thread_id: event.thread_ts,
prompts: [{title: "Summarize", message: "Summarize this thread"}]
)
end
bot.on_app_home_opened do |event|
slack.publish_home_view(user_id: event.user_id, view: {
type: "home",
blocks: [{type: "section", text: {type: "mrkdwn", text: "Welcome!"}}]
})
endThese Slack-only handlers receive:
on_assistant_thread_startedandon_assistant_context_changed:thread_id,channel_id,thread_ts,user_id, andcontext(ChatSDK::Events::AssistantContextwithchannel_id,team_id,enterprise_id,thread_entry_point, andforce_search)on_app_home_opened:user_id,channel_id, and optionaltabon_member_joined_channel:user_id,channel_id, and optionalinviter_id
Subscribe to the Slack events assistant_thread_started, assistant_thread_context_changed, app_home_opened, and member_joined_channel in your app's Event Subscriptions settings.
Handler Signatures
| Handler | Block signature | When it fires |
|---|---|---|
on_new_mention | |thread, message| | Bot is @-mentioned |
on_new_message(pattern) | |thread, message| | @-mention text matches pattern |
on_subscribed_message | |thread, message| | Message in a subscribed thread |
on_direct_message | |thread, message| | Direct message to the bot |
on_reaction | |event| | Emoji reaction added/removed |
on_action(action_id) | |event| | Card button/select interaction |
on_slash_command(command) | |event| | Slash command invoked |
on_assistant_thread_started | |event| | Slack assistant thread starts |
on_assistant_context_changed | |event| | Slack assistant thread context changes |
on_app_home_opened | |event| | Slack Home tab opens |
on_member_joined_channel | |event| | A member joins a Slack channel |
Multiple Handlers
You can register multiple handlers of the same type. They all fire for matching events:
bot.on_new_mention do |thread, message|
# Handler 1: logging
puts "Mention from #{message.author.name}: #{message.text}"
end
bot.on_new_mention do |thread, message|
# Handler 2: responding
thread.post("Acknowledged!")
endError Handling in Handlers
If a handler raises an exception, ChatSDK logs the error and continues processing other handlers. The webhook returns 200 to the platform so the event is not retried.
bot.on_new_mention do |thread, message|
raise "Something went wrong"
# This is logged but does not crash the process or return a 500.
endSee Error Handling for how to handle errors in your own code.