Beta — This SDK is experimental and under active development. APIs may change between minor versions. Not recommended for production use yet.
Unified Ruby SDK for building chat bots across Slack, Microsoft Teams, Google Chat, Mattermost, Discord, Telegram, Twilio SMS/MMS, Facebook Messenger, WhatsApp, X, Linear, and more. Write your bot logic once, deploy everywhere.
Inspired by and built upon the API design of Vercel's Chat SDK (TypeScript). This is an independent Ruby implementation — not a fork — with idiomatic Ruby patterns, a block-based cards DSL, and adapters tailored for the Ruby ecosystem.
Add the core gem and one or more adapters to your Gemfile:
gem "chat_sdk"
gem "chat_sdk-slack"
gem "chat_sdk-teams"
gem "chat_sdk-gchat"
gem "chat_sdk-mattermost"
gem "chat_sdk-discord"
gem "chat_sdk-telegram"
gem "chat_sdk-twilio"
gem "chat_sdk-messenger"
gem "chat_sdk-whatsapp"
gem "chat_sdk-x"
gem "chat_sdk-linear"
gem "chat_sdk-state-redis"
gem "chat_sdk-state-pg"
gem "chat_sdk-state-mysql"require "chat_sdk"
require "chat_sdk/slack"
require "chat_sdk/state/redis"
bot = ChatSDK::Chat.new(
user_name: "mybot",
adapters: {
slack: ChatSDK::Slack::Adapter.new(
bot_token: ENV["SLACK_BOT_TOKEN"],
signing_secret: ENV["SLACK_SIGNING_SECRET"]
)
},
state: ChatSDK::State::Redis.new(url: ENV["REDIS_URL"])
)
bot.on_new_mention do |thread, message|
thread.subscribe
thread.post("Hello! I'm listening to this thread.")
end
bot.on_subscribed_message do |thread, message|
thread.post("You said: #{message.text}")
endMount webhooks in Rails:
# config/routes.rb
mount Bot.webhooks[:slack], at: "/webhooks/slack"Or plain Rack:
# config.ru
map("/webhooks/slack") { run Bot.webhooks[:slack] }See the Getting Started guide for a full walkthrough.
- Event handlers — mentions, messages, reactions, button clicks, slash commands
- Streaming — stream LLM responses with progressive message editing and throttled updates
- Cards DSL — Ruby block-based interactive cards (Block Kit, Adaptive Cards, Google Chat Cards)
- Actions — handle button clicks and dropdown selections
- Modals — form dialogs with text inputs, dropdowns, and validation
- Slash commands — handle
/commandinvocations - Emoji & reactions — cross-platform emoji reactions
- Direct messages — initiate DMs programmatically
- Ephemeral messages — user-only visible messages
- Concurrency — distributed locking with configurable conflict policies (drop, force, callable)
Replace JSX with Ruby blocks:
thread.post(ChatSDK.card(title: "Incident #4821", subtitle: "SEV1 — API latency") do
text "Triggered by *Datadog* at 14:02 UTC"
fields do
field "Service", "ingest-api"
field "On-call", "@quentin"
end
divider
actions do
button "Acknowledge", id: "incident:ack", style: :primary, value: "4821"
button "Resolve", id: "incident:resolve", style: :danger, value: "4821"
link_button "Runbook", url: "https://rootly.com/runbooks/api-latency"
select id: "severity", placeholder: "Severity" do
option "SEV1", value: "sev1"
option "SEV2", value: "sev2"
end
end
end)Cards render natively on each platform — Slack Block Kit, Teams Adaptive Cards, Google Chat Card V2.
Three tiers of access — use the normalized API or drop down when you need platform-specific control:
# Tier 1 — normalized (cross-platform)
thread.post("hello")
# Tier 2 — adapter contract (still normalized message format)
bot.adapter(:slack).post_message(channel_id: "C123", message: msg)
# Tier 3 — raw platform client
bot.adapter(:slack).client.chat_postMessage(channel: "#ops", text: "raw")| Feature | Slack | Teams | GChat | Mattermost | Discord | Telegram | Twilio | Messenger | X | Linear | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Post/Edit/Delete | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓/✗/✓ | ✓/✗/✗ | ✓/✗/✗ | ✓/✗/✓ | ✓ |
| Ephemeral | ✓ | ✗ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Reactions | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✓ |
| File uploads | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | ✗ |
| Modals | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| Streaming | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✓ |
| DMs | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
| History | ✓ | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ✗ | ✗ | ✓ | ✓ |
| Typing | ✓ | ✓ | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ✗ | ✗ | ✗ |
Platform clients:
- Slack — wraps slack-ruby-client
- Teams — raw Faraday client (no Ruby Bot Framework SDK exists)
- GChat — wraps google-apps-chat-v1
- Mattermost — raw Faraday client wrapping the Mattermost REST API
- Discord — raw Faraday client wrapping the Discord REST API v10 with Ed25519 signature verification
- Telegram — raw Faraday client wrapping the Telegram Bot API with webhook secret token verification and inline keyboard rendering
- Twilio — raw Faraday client wrapping the Twilio REST API with HMAC-SHA1 signature verification for SMS/MMS messaging
- Messenger — raw Faraday client wrapping the Facebook Messenger Send API with HMAC-SHA256 signature verification and Generic/Button template rendering
- WhatsApp — raw Faraday client wrapping the WhatsApp Business Cloud API with HMAC-SHA256 signature verification and interactive message rendering
- X -- raw Faraday client wrapping the X API v2 with HMAC-SHA256 webhook signature verification for tweets, DMs, and likes
- Linear -- raw Faraday client wrapping the Linear GraphQL API with HMAC-SHA256 webhook signature verification for issue comment threading
For agent-readable documentation, see llms.txt (page index).
Full documentation is available in the docs/ directory.
See CONTRIBUTING.md for guidance. For security vulnerabilities, see SECURITY.md.
Thanks to the Vercel team for creating the original Chat SDK (MIT). Their elegant API design — normalized events, pluggable adapters, cards abstraction, and streaming model — is what made this Ruby port possible. We're grateful for their work and the open source community around it.
MIT — see LICENSE.
Made by Rootly
