Thread
The per-conversation handle — post and stream messages, run the agent, block on a human choice, and reach platform power through capability-gated methods.
Overview
A Thread is the per-conversation handle passed to every handler, tool context, and interaction context. It posts UI (JSX from the component vocabulary or plain strings), drives the agent run loop, resolves human-in-the-loop choices, and exposes platform power through capability-gated methods that degrade gracefully on surfaces that don't support them.
interface Thread {
readonly platform: string;
post(ui: Renderable): Promise<MessageRef>;
update(ref: MessageRef, ui: Renderable): Promise<MessageRef>;
delete(ref: MessageRef): Promise<void>;
stream(src: string | AsyncIterable<string>): Promise<MessageRef>;
runAgent(input?: {
context?: ContextEntry[];
tools?: BotTool[];
prompt?: string;
}): Promise<MessageRef | undefined>;
resume(value: unknown): Promise<MessageRef | undefined>;
awaitChoice<T = unknown>(ui: Renderable): Promise<T>;
getMessages(): Promise<ThreadMessage[]>;
lookupUser(query: string): Promise<PlatformUser | undefined>;
postFile(args: {
bytes: Uint8Array;
filename: string;
title?: string;
altText?: string;
}): Promise<{ ok: boolean; fileId?: string; error?: string }>;
}Properties
Prop
Type
Methods
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Usage
bot.onMention(async ({ thread, message }) => {
// Run the agent with extra per-run context:
await thread.runAgent({
context: [
{ description: "Requesting user", value: message.user.name ?? message.user.id },
],
});
});// Inside a tool: read the thread, then block on approval.
async handler({ summary }, { thread }) {
const choice = await thread.awaitChoice<{ confirmed: boolean }>(
<ConfirmWrite action={summary} />,
);
return choice ?? { confirmed: false }; // serialized for the agent automatically
}Behavior
- Capability gating keeps tools portable —
getMessages/lookupUser/postFiledelegate to the adapter when supported and degrade gracefully ([]/undefined/{ ok: false }) when not, so the same tool runs on any surface. - Per-run merging —
runAgent'stoolsandcontextapply to that run only, layered on top of the bot-level defaults. - History reconstruction — on Slack, the conversation's
agent.messagesare rebuilt from Slack history each turn; the platform is the source of truth, so bot restarts don't lose conversations.
Related
- createBot — where handlers receive a Thread
- defineBotTool — tools receive the Thread in
ctx.thread - Button — interactive messages and
awaitChoice - slack() — how the Slack adapter backs these methods