Trying Out the New Slack API Methods [Streaming Edition]

Trying Out the New Slack API Methods [Streaming Edition]

An introduction to Slack's text streaming API: the chat.startStream, chat.appendStream and chat.stopStream methods, and incremental block updates via the chunks parameter, explained with verification examples.
2026.09.01

This page has been translated by machine translation. View original

Since the start of 2026, new blocks have been steadily added to Slack's Block Kit. In this series, we introduce these new blocks and related APIs by actually trying them out.

  • Part 1: Data

https://dev.classmethod.jp/articles/slack-block-kit-new-data-display-blocks/

  • Part 2: General Display

https://dev.classmethod.jp/articles/slack-block-kit-new-general-display-blocks-guide/

  • Part 3: Agents

https://dev.classmethod.jp/articles/slack-block-kit-agent-blocks-guide/

  • Part 4: Streaming (this article)
  • Part 5: Validation and CI

In Part 4, we introduce three methods of the text streaming API: chat.startStream / chat.appendStream / chat.stopStream. These APIs let a Slack app achieve the familiar LLM-app experience where a response is displayed gradually.

Until now, you could create a streaming-like display by repeatedly editing the same message with chat.update. However, this approach required preparing and resending the full text with every request, and it was easy to hit rate limits as you increased the update frequency.

In contrast, with the streaming API you only need to send the appended portion, and the rate limit for appendStream, which handles appending, is relaxed, so it has become even easier to use.

Incidentally, this API is also what powers the mechanism for incrementally updating the plan block and task_card block introduced in Part 3.

Note that this time we can't verify with the familiar Block Kit Builder, so we'll call the APIs directly using the slack api command of the Slack CLI.
For details on this command, please refer to the following article.

https://dev.classmethod.jp/articles/slack-cli-slack-api/

Method Overview

Method Role Rate limit
chat.startStream[1] Starts a streaming message Tier 2 (20+ per minute)
chat.appendStream[2] Appends to a message being streamed Tier 4 (100+ per minute)
chat.stopStream[3] Ends the streaming and finalizes the message Tier 2 (20+ per minute)

All three methods require only the chat:write scope. By passing the timestamp received in the response of start to append and stop, you append to and finalize a single message.

Main Parameters

chat.startStream

Item Description
channel Required. The ID of the channel, thread, or DM
markdown_text Text in standard Markdown format. Up to 12,000 characters
chunks An array of streaming chunks. Cannot be used together with markdown_text
thread_ts The thread to reply to. In a regular channel, omitting it results in an invalid_thread_ts error
recipient_user_id / recipient_team_id The IDs of the user and team that receive the streaming. Required when streaming to a channel
task_display_mode How tasks are displayed. timeline (task cards are displayed individually, alternating with text) or plan (displayed together in a plan block). The default is timeline

An important point is that in a regular channel, streaming is only possible as a thread reply.

Delivery as a regular post rather than a reply is possible only in channels with a special setup where the entire channel acts as a single session. Also, when delivering to a channel, specifying recipient_user_id and recipient_team_id is mandatory. This is a mechanism that lets Slack know who the streaming is intended for.

chat.appendStream

channel and ts are required, and you pass the content via markdown_text or chunks. markdown_text works by sending only the appended portion, not resending the full text.

chat.stopStream

Similarly, channel and ts are required, and you pass the content via markdown_text or chunks. In addition, it has the following specific items.

Item Description
blocks An array of blocks rendered at the end of the finalized message. Up to 50, separate from the 50 via chunks
metadata Message metadata
session_status The session status to set after streaming ends. active / processing / suspended / closed

Streaming Text with markdown_text

Assuming a bot that answers questions about expense reimbursement, let's call the three methods in order. First is the streaming start process.

$ slack api chat.startStream --json '{
  "channel": "C0123456789",
  "thread_ts": "<スレッド元となるメッセージのタイムスタンプ>",
  "recipient_team_id": "T0123456789",
  "recipient_user_id": "U0123456789",
  "markdown_text": "調べています。\n\n"
}'

The ts in the response becomes the identifier of the streaming message. We specify this ts to append.

$ slack api chat.appendStream --json '{
  "channel": "C0123456789",
  "ts": "<ストリーミング開始処理レスポンスのタイムスタンプ>",
  "markdown_text": "## 出張費の精算期限\n\n**帰着日から 1 週間以内**に申請してください。"
}'

Finally, we stop it. We'll pass the context_actions block introduced in Part 3 to blocks to add feedback buttons at the end of the finalized message.

$ slack api chat.stopStream --json '{
  "channel": "C0123456789",
  "ts": "<ストリーミング開始処理レスポンスのタイムスタンプ>",
  "blocks": [
    {
      "type": "context_actions",
      "elements": [
        {
          "type": "feedback_buttons",
          "action_id": "answer_feedback",
          "positive_button": {
            "text": { "type": "plain_text", "text": "👍" },
            "value": "positive_feedback"
          },
          "negative_button": {
            "text": { "type": "plain_text", "text": "👎" },
            "value": "negative_feedback"
          }
        }
      ]
    }
  ]
}'

The streaming in action

Unlike overwriting a message, you only need to send the appended portion, so you can simply send the LLM output as it is. The display suddenly looks the part!

Streaming the Thought Process with chunks

Next, let's use the chunks parameter to incrementally update the plan block introduced in Part 3. There are four types of chunks.

Chunk type Purpose
markdown_text Appending Markdown text
task_update Adding or updating tasks. Those with the same id are treated as updates
plan_update Updating the plan title
blocks Adding an array of blocks. Up to 50 per array; any excess is discarded and a warning is issued via the API

The structure of the task_update chunk is almost the same as the task_card block, except that details and output are strings rather than rich_text. Also, the chunk size of task_update and plan_update is limited to 256 characters.

We'll start streaming with plan specified for task_display_mode and send tasks in order.

$ slack api chat.startStream --json '{
  "channel": "C0123456789",
  "thread_ts": "<スレッド元となるメッセージのタイムスタンプ>",
  "recipient_team_id": "T0123456789",
  "recipient_user_id": "U0123456789",
  "task_display_mode": "plan",
  "chunks": [
    { "type": "plan_update", "title": "経費精算の質問に回答中" },
    { "type": "task_update", "id": "step_1", "title": "社内ドキュメントを検索", "status": "in_progress" }
  ]
}'

The completion of a task and the start of the next task are expressed with task_update for the same id. For ts, as before, specify the value from the start response.

$ slack api chat.appendStream --json '{
  "channel": "C0123456789",
  "ts": "<ストリーミング開始処理レスポンスのタイムスタンプ>",
  "chunks": [
    { "type": "task_update", "id": "step_1", "title": "社内ドキュメントを検索", "status": "complete", "output": "経費精算ガイドが見つかりました" },
    { "type": "task_update", "id": "step_2", "title": "回答を生成", "status": "in_progress" }
  ]
}'

Task streaming in a plan block

In Part 3 we pasted the plan block as static JSON, but this is the more practical implementation.

Summary

In this article, we introduced the three methods of the text streaming API.

From incremental text display to updating plan blocks and placing feedback buttons, all of it can now be achieved with simple implementations, and it feels like display components for agents are becoming easier and easier to use. If you've been using the conventional chat.update, why not take this opportunity to try the new methods?

Next time is finally the last installment. Part 5 is Validation and CI, where we'll try payload validation with blocks.validate and integrating it into CI. Look forward to it!

脚注
  1. https://docs.slack.dev/reference/methods/chat.startStream ↩︎

  2. https://docs.slack.dev/reference/methods/chat.appendStream ↩︎

  3. https://docs.slack.dev/reference/methods/chat.stopStream ↩︎


AI白書2026 配布中

クラスメソッドが独自に行なったAI診断調査をもとに、企業のAI活用の現在地を調査レポートとしてまとめました。企業規模別の活用度傾向に加え、規模を超えてAI活用を進める企業に共通する取り組みまで、自社の現在地を捉えるためのヒントにぜひ。

AI白書2026

無料でダウンロードする

Share this article