Proposal
Problem
The Slack adapter always streams replies live — native streaming
(chat.startStream + assistant.threads.setStatus) when assistant_mode is on,
or a post+edit placeholder otherwise. This is great UX for a single bot, but in
multi-agent threads (several openab bots, or openab alongside other Slack bots in
one channel) it has a sharp edge.
Consider a thread with two bots:
- user → bot A
- bot A → bot B (bot A's reply
@-mentions bot B)
- bot B → bot A
At step 2, no other bot has posted in the thread yet, so bot A still treats it
as a single-bot thread and streams its reply via post+edit. Each edit emits a
message_changed event → bot B's app_mention re-fires once per edit, so bot B
responds to intermediate/partial states instead of bot A's single final message.
The existing other_bot_present gate only disables streaming after another bot
has posted — it cannot help on the kickoff message that first mentions bot B. There
is no way for an operator to deterministically opt a deployment into send-once
behaviour.
[gateway] already exposes a streaming switch (defaults false). Slack has no
equivalent.
Proposed shape
Add one optional boolean to [slack], default true (preserves current behaviour):
[slack]
streaming = true # default — live streaming, as today
# streaming = false # always post a single final message (send-once)
When streaming = false:
- No native streaming (no
chat.startStream / streamed assistant.threads.setStatus).
- No post+edit placeholder.
- The adapter posts exactly one final
chat.postMessage per turn.
- Independent of
assistant_mode — the assistant status API (reaction / set-status)
is unaffected; only the message streaming path is gated.
Mirrors [gateway].streaming in concept; the default deliberately differs (true
for Slack to preserve the current streaming UX, vs false for gateway).
Key behaviour
- Gating points:
use_streaming() and uses_native_streaming() both AND-in the new flag.
assistant_mode status / reactions are unaffected by the switch.
- Default
true → zero behaviour change for existing deployments.
Open questions
- Naming:
streaming (mirrors gateway) vs something more explicit like
live_streaming / send_once?
- Scope: Slack-only for now, or land the same toggle on Discord for symmetry?
(Discord has no post+edit streaming, so the multi-agent concern is Slack-specific.)
- Default: keep
true (current behaviour) — confirming that's the preferred default.
I have a working implementation + tests for the Slack side and am happy to open a
PR if the shape looks good.
Update (2026-06-18)
Beyond the streaming toggle, PR #1115 also introduces send-once narration trimming — only the final answer block (text after the last tool call) is delivered, dropping inter-tool narration. Per maintainer discussion this is controlled by a dedicated narration_display flag (default false), decoupled from streaming, and implemented in the shared adapter layer so it applies to any send-once turn (not just Slack). Supersedes the per-backend filters in #1030 / #1032.
Proposal
Problem
The Slack adapter always streams replies live — native streaming
(
chat.startStream+assistant.threads.setStatus) whenassistant_modeis on,or a post+edit placeholder otherwise. This is great UX for a single bot, but in
multi-agent threads (several openab bots, or openab alongside other Slack bots in
one channel) it has a sharp edge.
Consider a thread with two bots:
@-mentions bot B)At step 2, no other bot has posted in the thread yet, so bot A still treats it
as a single-bot thread and streams its reply via post+edit. Each edit emits a
message_changedevent → bot B'sapp_mentionre-fires once per edit, so bot Bresponds to intermediate/partial states instead of bot A's single final message.
The existing
other_bot_presentgate only disables streaming after another bothas posted — it cannot help on the kickoff message that first mentions bot B. There
is no way for an operator to deterministically opt a deployment into send-once
behaviour.
[gateway]already exposes astreamingswitch (defaultsfalse). Slack has noequivalent.
Proposed shape
Add one optional boolean to
[slack], defaulttrue(preserves current behaviour):When
streaming = false:chat.startStream/ streamedassistant.threads.setStatus).chat.postMessageper turn.assistant_mode— the assistant status API (reaction / set-status)is unaffected; only the message streaming path is gated.
Mirrors
[gateway].streamingin concept; the default deliberately differs (truefor Slack to preserve the current streaming UX, vs
falsefor gateway).Key behaviour
use_streaming()anduses_native_streaming()both AND-in the new flag.assistant_modestatus / reactions are unaffected by the switch.true→ zero behaviour change for existing deployments.Open questions
streaming(mirrors gateway) vs something more explicit likelive_streaming/send_once?(Discord has no post+edit streaming, so the multi-agent concern is Slack-specific.)
true(current behaviour) — confirming that's the preferred default.I have a working implementation + tests for the Slack side and am happy to open a
PR if the shape looks good.
Update (2026-06-18)
Beyond the
streamingtoggle, PR #1115 also introduces send-once narration trimming — only the final answer block (text after the last tool call) is delivered, dropping inter-tool narration. Per maintainer discussion this is controlled by a dedicatednarration_displayflag (defaultfalse), decoupled fromstreaming, and implemented in the shared adapter layer so it applies to any send-once turn (not just Slack). Supersedes the per-backend filters in #1030 / #1032.