💎 ChatSDK Ruby

API: Thread

ChatSDK::Thread is the primary interface for sending messages, managing subscriptions, and interacting with threads.

ChatSDK::Thread represents a conversation thread. It is the primary interface for sending messages, managing subscriptions, and interacting within a thread.

Constructor

ChatSDK::Thread.new(
  id:,
  channel_id:,
  adapter:,
  chat:
)
ParameterTypeRequiredDefaultDescription
idStringYes--Thread identifier
channel_idStringYes--Channel this thread belongs to
adapterAdapter::BaseYes--The platform adapter
chatChatYes--The parent Chat instance

Threads are typically created via Channel#thread rather than directly.

Attributes

AttributeTypeDescription
idStringThread identifier
channel_idStringChannel this thread belongs to
adapterAdapter::BaseThe platform adapter
chatChatThe parent Chat instance

Instance Methods

post(content)

Posts a message to the thread. Accepts a String, Cards::Node, or PostableMessage.

thread.post("Hello!")
thread.post(ChatSDK.card(title: "Info") { text "Details here" })

Returns the result from the adapter (typically a Message with the posted message's ID).

post_ephemeral(content, user_id:)

Posts a message visible only to the specified user.

thread.post_ephemeral("Only you see this", user_id: "U123")
ParameterTypeRequiredDescription
contentString, Cards::Node, or PostableMessageYesMessage content
user_idStringYesUser who will see the ephemeral message

Raises NotSupportedError if the adapter does not support :ephemeral_messages.

post_stream(placeholder: nil, &block)

Posts a streaming message that is updated incrementally via edits. Creates a Streaming::Stream object using the chat's streaming_update_interval config.

thread.post_stream(placeholder: "Loading...") do |stream|
  stream << "First chunk "
  stream << "second chunk "
  stream << "done."
end
ParameterTypeRequiredDefaultDescription
placeholderStringNonilInitial message text posted before streaming begins

The block receives a Streaming::Stream that supports << to append text chunks. The stream flushes edits at the configured streaming_update_interval.

post_ai_stream(enumerable, placeholder: "Thinking...")

Streams an AI response (from any Enumerable that yields string chunks) into the thread.

chunks = ai_client.chat_stream(messages: msgs)
thread.post_ai_stream(chunks, placeholder: "Thinking...")
ParameterTypeRequiredDefaultDescription
enumerableEnumerableYes--An enumerable yielding string chunks
placeholderStringNo"Thinking..."Initial placeholder text

Delegates to ChatSDK::AI::StreamHandler.stream_to_thread.

edit(message_id, content)

Edits an existing message.

result = thread.post("Draft")
thread.edit(result.id, "Final version")
ParameterTypeRequiredDescription
message_idStringYesID of the message to edit
contentString, Cards::Node, or PostableMessageYesNew message content

delete(message_id)

Deletes a message.

result = thread.post("Temporary")
thread.delete(result.id)
ParameterTypeRequiredDescription
message_idStringYesID of the message to delete

react(message_id, emoji)

Adds an emoji reaction to a message.

thread.react(message.id, "thumbsup")
ParameterTypeRequiredDescription
message_idStringYesID of the message to react to
emojiStringYesEmoji name (e.g. "thumbsup")

unreact(message_id, emoji)

Removes an emoji reaction from a message.

thread.unreact(message.id, "thumbsup")
ParameterTypeRequiredDescription
message_idStringYesID of the message
emojiStringYesEmoji name to remove

upload(io:, filename:, comment: nil)

Uploads a file to the thread.

File.open("report.pdf", "rb") do |f|
  thread.upload(io: f, filename: "report.pdf", comment: "Monthly report")
end
ParameterTypeRequiredDefaultDescription
ioIOYes--Readable IO object
filenameStringYes--Name for the uploaded file
commentStringNonilOptional comment attached to the upload

Raises NotSupportedError if the adapter does not support :file_uploads.

messages(cursor: nil, limit: 50)

Fetches conversation history for the thread.

messages, next_cursor = thread.messages(limit: 20)
ParameterTypeRequiredDefaultDescription
cursorStringNonilPagination cursor from a previous call
limitIntegerNo50Maximum number of messages to return

Returns the result from the adapter's fetch_messages (typically [Array<Message>, cursor]).

state

Returns per-thread state data, or nil if none is stored.

data = thread.state  # => {"count" => 3} or nil

set_state(value)

Stores per-thread state data with a 30-day TTL.

thread.set_state({"count" => 3, "last_run" => Time.now.iso8601})
ParameterTypeRequiredDescription
valueanyYesValue to store (must be serializable by the state backend)

subscribe

Subscribes the bot to future messages in this thread. Messages in subscribed threads trigger the on_subscribed_message handler.

thread.subscribe

unsubscribe

Unsubscribes from the thread.

thread.unsubscribe

subscribed?

Returns true if the bot is currently subscribed to this thread.

thread.subscribed?  # => true / false

mention_user(user_id)

Returns a formatted user mention string for the current platform.

thread.mention_user("U123")  # => "<@U123>" (Slack)
ParameterTypeRequiredDescription
user_idStringYesPlatform user ID

open_modal(trigger_id:, modal:)

Opens a modal dialog. Requires a trigger_id from an interactive event (action or slash command).

modal = ChatSDK::Modals::Builder.new(title: "Feedback") do
  text_input id: "comment", label: "Comment", multiline: true
end.build

thread.open_modal(trigger_id: event.trigger_id, modal: modal)
ParameterTypeRequiredDescription
trigger_idStringYesTrigger ID from the originating event
modalCards::NodeYesModal node built with Modals::Builder

Raises NotSupportedError if the adapter does not support :modals.

Equality

Two threads are equal (==, eql?) if they have the same id and channel_id. The hash method is consistent with equality, making threads usable as hash keys.

On this page