Skip to content

Streaming content not visible in real-time with assistant.threads API #2696

@buremba

Description

@buremba

Summary

When using chatStream() with assistant.threads.setStatus(), the streamed content is not visible to users in real-time. Instead, users see the loading indicator until the stream completes, then all content appears at once.

Environment

  • @slack/bolt: 4.5.0
  • @slack/web-api: 7.11.0
  • Platform: Slack Desktop App (macOS) / Slack Web
  • Workspace type: [Free]

Expected Behavior

Based on this comment:

"the loading indicator should be replaced with the received text for the recipient once the first part of the message is received"

Users should see:

  1. Initial loading status ("Processing...")
  2. First chunk appears immediately after chatStream() is created
  3. Status updates show progress ("Step 1 of 3")
  4. Additional chunks appear as they're appended
  5. Real-time streaming experience

Actual Behavior

CleanShot.2025-10-23.at.18.38.36.mp4

Users see:

  1. Loading indicator the entire time (no matter how long does it take to stop the stream, tried 5mins as well)
  2. Content only appears when stream.stop() is called
  3. All chunks appear at once
  4. No real-time streaming visible

Minimal Reproduction

#!/usr/bin/env bun
import { WebClient } from "@slack/web-api";

const client = new WebClient(process.env.SLACK_BOT_TOKEN);
const CHANNEL = "YOUR_CHANNEL";
const USER = "YOUR_USER";

async function main() {
  // Get team ID
  const auth = await client.auth.test();
  const team = auth.team_id;

  // Create thread
  const userMsg = await client.chat.postMessage({
    channel: CHANNEL,
    text: "Testing streaming",
  });
  const thread = userMsg.ts;

  // Set initial status
  await client.assistant.threads.setStatus({
    channel_id: CHANNEL,
    thread_ts: thread,
    status: "Processing...",
    loading_messages: ["Analyzing request"],
  });

  await sleep(2000);

  // Start streaming
  const streamer = client.chatStream({
    channel: CHANNEL,
    thread_ts: thread,
    recipient_team_id: team,
    recipient_user_id: USER,
    markdown_text: "**Starting process...**",
  });

  await sleep(2000);

  // Append chunks with status updates
  await client.assistant.threads.setStatus({
    channel_id: CHANNEL,
    thread_ts: thread,
    status: "Step 1 of 3",
  });
  await streamer.append({ markdown_text: "\n\n**Step 1**: First chunk" });

  await sleep(3000);

  await client.assistant.threads.setStatus({
    channel_id: CHANNEL,
    thread_ts: thread,
    status: "Step 2 of 3",
  });
  await streamer.append({ markdown_text: "\n\n**Step 2**: Second chunk" });

  await sleep(3000);

  await client.assistant.threads.setStatus({
    channel_id: CHANNEL,
    thread_ts: thread,
    status: "Step 3 of 3",
  });
  await streamer.append({ markdown_text: "\n\n**Step 3**: Final chunk" });

  await sleep(2000);

  // Stop stream
  await streamer.stop();
  await client.assistant.threads.setStatus({
    channel_id: CHANNEL,
    thread_ts: thread,
    status: "",
  });
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

main().catch(console.error);

Steps to Test

  1. Run the reproduction script
  2. Watch the Slack thread in real-time
  3. Observe when content becomes visible

Question

  • Is this the expected behavior?
  • Should content be visible incrementally as chunks are appended or does Slack buffer streaming content until stream.stop() is called?
  • Do status updates work alongside streaming?

Reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    docsM-T: Documentation work onlyquestionM-T: User needs support to use the project

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions