showcase/shell-docs/src/content/reference/channels/classes/Thread.mdx
A Channels Thread is the SDK handle for one native conversation. Handlers,
tools, and JSX callbacks receive it.
| Property | Type | Description |
|---|---|---|
conversationKey | string | Stable managed conversation key. Also passed to the agent(threadId) factory. |
platform | string | Native delivery provider. Managed Channels report "slack" or "teams". |
supportsBlockingChoice | boolean | undefined | false on the managed path. Use post-and-resume instead of awaitChoice. |
| Method | Returns | Description |
|---|---|---|
post(ui) | Promise<MessageRef> | Send text or portable JSX. |
update(ref, ui) | Promise<MessageRef> | Replace a prior message. |
delete(ref) | Promise<void> | Remove a prior message when supported. |
stream(source) | Promise<MessageRef> | Stream text where the adapter supports streaming. |
postFile(args) | Promise<{ ok, fileId?, error? }> | Upload bytes with a filename when supported. |
postEphemeral(user, ui, { fallbackToDM }) | Promise<EphemeralResult | null> | Provider-capability-gated private reply. The required boolean chooses whether to fall back to a direct message. |
const ref = await thread.post("Working…");
await thread.update(ref, "Done.");
The MessageRef returned by thread.post() is updateable or deletable only
during the current managed delivery. Do not persist arbitrary refs and reuse
them to update or delete messages across deliveries.
In a later interaction, use the interaction-provided message.ref, which
Intelligence stamps for that delivery. Only attempt an update when
message.ref.id is non-empty, and treat that update as best-effort.
Capability-result methods such as postFile, react, and
setSuggestedPrompts can return { ok: false } when unavailable. Message
operations such as update, delete, and stream can reject when the current
adapter or provider cannot perform them, so catch failures when they are not
allowed to fail the workflow.
| Method | Returns | Description |
|---|---|---|
runAgent(input?) | Promise<MessageRef | undefined> | Run the thread's agent and render its output. |
resume(value, options?) | Promise<MessageRef | undefined> | Consume the action continuation and re-enter an interrupted run. |
runAgent accepts:
| Field | Type | Description |
|---|---|---|
prompt | string | AgentContentPart[] | Explicit user turn. When omitted in a message handler, the SDK injects the inbound text or content parts automatically. |
context | ContextEntry[] | Context for this run only. |
tools | ChannelTool[] | Tools for this run only. |
transcript | boolean | { limit?: number } | Optional SDK transcript bridge when identifyUser resolves a user and transcripts are configured. |
memory | { user?, project? } | Per-run Intelligence Memory access. Each scope is "none", "read", or "read-write"; omission disables Memory. |
channel.onMessage(async ({ thread, message }) => {
await thread.runAgent({
prompt: message.contentParts?.length
? [
...(message.text
? [{ type: "text" as const, text: message.text }]
: []),
...message.contentParts,
]
: message.text,
context: [{ description: "Originating platform", value: message.platform }],
});
});
For managed approvals, post a registered component, return from the interrupt
handler, and call resume(value) when a later click arrives. Do not call
awaitChoice; see the interactive messages guide for
Slack or Teams.
Personal Memory on resume needs a trusted subject selector:
await thread.resume(value, {
memory: { user: "read", project: "read" },
subject: "initiator", // or "actor"
});
initiator keeps the application user that started this HITL chain. actor
uses the application user resolved for the current interaction. Project-only
Memory needs no subject and carries no made-up user. A continuation expires
with action retention and can start only one resumed run.
Memory and continuation failures expose stable codes:
channel_memory_grant_invalid, channel_memory_user_required, and
channel_memory_unavailablechannel_memory_subject_required, channel_continuation_required,
channel_continuation_mismatch, and channel_action_expired| Method | Returns | Description |
|---|---|---|
getMessages() | Promise<ThreadMessage[]> | Managed history in chronological order; returns [] if unavailable. |
lookupUser(query) | Promise<ProviderActor | undefined> | Provider lookup where supported. |
| Method | Returns | Description |
|---|---|---|
state<T>() | Promise<T | undefined> | Read the value stored for this conversation. |
setState<T>(value) | Promise<void> | Replace the full stored value. Validated when store.state is configured. |
State uses the Channel's StateStore. Without a durable store.adapter, the
default MemoryStore keeps it only in the current process. See the threads and
state guide for Slack or
Teams.
| Method | Purpose |
|---|---|
react(ref, emoji) / unreact(ref, emoji) | Add or remove the bot's reaction. |
setSuggestedPrompts(prompts, options?) | Set prompts on surfaces such as an assistant pane. |
setTitle(title) | Name the conversation. |
subscribe() / unsubscribe() / isSubscribed() | Store a subscription flag. Proactive routing from that flag is not implemented. |
Managed Slack and Teams support react and unreact for the portable reaction
set: thumbs_up, thumbs_down, heart, fire, eyes, refresh, thinking,
and tada. Other methods remain provider-capability dependent; check { ok }
when the method returns a capability result.