Thread
A Thread represents a conversation thread on any platform. Event handlers receive one, and you can also create thread handles with chat.thread() or chat.openDM().
Properties
Prop
Type
post
Post a message to the thread. Accepts strings, structured messages, cards, streams, and PostableObject instances (Plan, StreamingPlan).
Parameters: message: string | PostableMessage | ChatElement
ChatElement covers card and modal elements, whether you write them in JSX or build them with functions such as Card().
Returns: Promise<SentMessage | PostableObject>. Plain messages and streams return a SentMessage with edit(), delete(), addReaction(), and removeReaction() methods. Plan and StreamingPlan inputs return the same object so you can keep mutating it.
See Posting Messages for details on each format.
reply
Post a message with a native reference to another message.
Parameters: target: string | Message, message: string | AdapterPostableMessage | AsyncIterable<string | StreamChunk | StreamEvent> | ChatElement
Returns: Promise<SentMessage>
The target Message must belong to the same thread. Streams are buffered before sending. Unlike post(), reply() does not accept Plan or StreamingPlan. Adapters without native message reply support throw NotImplementedError.
Prefer passing the Message over its ID. The Message is checked against this thread and carried through to SentMessage.replyTo and cached thread history. A bare ID is only resolved to a Message when the thread already holds it in recentMessages; otherwise the reply is still sent, but replyTo is left undefined.
postEphemeral
Post a message visible only to a specific user.
Prop
Type
Returns: Promise<EphemeralMessage | null>
schedule
Schedule a message for future delivery. Only the Slack adapter supports this. Other adapters throw NotImplementedError.
Parameters: message: AdapterPostableMessage | ChatElement, options: { postAt: Date }
Returns: Promise<ScheduledMessage>
Streaming and file uploads are not supported in scheduled messages.
getParticipants
Get the unique human participants in a thread. Returns deduplicated authors and excludes all bots. Use it to subscribe only to 1:1 conversations and unsubscribe when others join.
Each call fetches the full message history to find all participants, which takes multiple platform API calls on threads with long history. Consider checking message.author against a known set before calling getParticipants() on every incoming message.
subscribe / unsubscribe
Manage thread subscriptions. Subscribed non-DM threads route all messages to onSubscribedMessage handlers. DM threads route to onDirectMessage first when a direct message handler is registered.
Subscriptions persist across restarts through your state adapter.
state
Store typed, per-thread state that persists across requests. State has a 30-day TTL.
startTyping
Show a typing indicator in the thread. No-op on platforms that don't support
it. With Slack Agent messaging, calling this without a custom status sets the
session to processing and identifies the initiating user. Slack's native stop
button also requires the agent_session_stopped event subscription.
A custom status uses the legacy assistant.threads.setStatus compatibility
bridge for loading labels instead. That endpoint cannot receive the initiating
user, and an existing native processing indicator can take precedence over the
label. Use the default indicator when you need native session behavior.
signal
An AbortSignal for the active turn. Slack aborts it when the user clicks the
native agent-session stop button, including when the stop webhook reaches a
different serverless instance sharing the same state adapter.
Pass it to model and tool APIs so cancellation stops upstream work:
Threads created outside an incoming handler expose a signal that remains unaborted.
markAsRead
Mark an inbound message as read. WhatsApp, Messenger, and XChat support this capability. Other adapters throw NotImplementedError.
Inside a message handler, omit the argument to mark the current message:
Pass a Message or message ID when targeting a message explicitly:
A Message must belong to the thread, and passing one from another thread throws. A bare message ID is sent to the adapter as given, since there is nothing to check it against. Calling markAsRead() without an argument outside a message handler throws because there is no current message.
Platforms may advance the conversation's read state through the target message, which also marks earlier messages as read.
messages / allMessages
Iterate through message history.
refresh
Re-fetch messages from the API and update recentMessages.
mentionUser
Get a platform-specific @-mention string for a user.
Serialization
Threads can be serialized for workflow engines and external systems. The serialized thread includes the current message if one is available.
The serialized format includes the thread ID, channel ID, adapter name, DM status, and the current message when present.
Deserialization
Use bot.reviver() as a JSON.parse reviver to automatically restore Thread and Message objects from serialized payloads:
The reviver calls ThreadImpl.fromJSON() and Message.fromJSON() for any serialized objects it encounters.
When a restored thread starts streaming, it uses its Chat instance's fallbackStreamingPlaceholderText and streamingUpdateIntervalMs defaults. bot.reviver() binds restored threads to that bot; standalone and Workflow deserialization bind to the registered singleton on first runtime access. These settings are not stored in the serialized payload, so resumed work uses the receiving bot's configuration. An explicit StreamingPlan update interval still takes precedence.
If you pass an adapter directly to ThreadImpl.fromJSON(data, adapter), streaming can work without a registered Chat instance, using the default settings. Streaming defaults come only from a Chat instance that has that exact adapter registered, under any key. If the registered instance doesn't own the adapter, state still comes from the registered singleton, as in earlier versions. Prefer bot.reviver() to bind ownership explicitly.
ScheduledMessage
Returned by thread.schedule() and channel.schedule().
Prop
Type
SentMessage
Returned by thread.post(). Extends Message with mutation methods.
Prop
Type
Read more
Threads, Messages, and Channels
Work with threads, messages, and channels across platforms.
Posting Messages
Different ways to render and send messages with thread.post().
Channel
Channel container that holds threads, with methods for listing, posting, and iteration.
Message
Normalized message format with text, AST, author, and metadata.