Context
We implemented per-thread session isolation for Slack in the feat/thread-isolation branch. Each Slack thread gets its own OpenCode session, and users can continue chatting in a thread without re-mentioning the bot.
Three other platforms also support threads:
Mattermost (straightforward)
Mattermost threads work very similarly to Slack. The REST API POST /api/v4/posts accepts a root_id field to reply in a thread. The WebSocket posted event includes root_id when a message is a thread reply.
Implementation would closely mirror the Slack approach:
- Session key:
channelId:rootId
- Reply routing: set
root_id on all outgoing posts
- Implicit follow-ups: forward plain thread replies when a session exists
- The WebSocket event handler (
handlePostedEvent) already receives post.root_id
Discord (different model)
Discord threads are actually separate channels (ThreadChannel). The bot needs to:
- Join threads explicitly or listen to
threadCreate events
- Messages in threads come from separate channel IDs
- Thread channels have a
parentId pointing to the parent channel
This is architecturally different from Slack/Mattermost. The current per-channel session key might already provide some isolation since thread channels have unique IDs. Needs investigation into whether the bot receives thread messages with current intents.
Matrix (newer spec)
Matrix added threads in spec v1.4 (MSC3440) via m.thread relations. The matrix-bot-sdk supports them. Thread replies include a m.relates_to field with rel_type: "m.thread" and event_id pointing to the thread root.
Client support varies -- Element supports threads well, but some clients show them as flat messages. Worth implementing but should be tested with real Matrix clients.
WhatsApp
No thread concept. Skip.
Design note: configurable vs always-on
Currently the Slack implementation is hardcoded to ALWAYS reply in threads. There is no config option to fall back to channel-level replies.
We should consider adding a config flag (e.g., threadIsolation: true/false in chat-bridge.json) so users can choose:
true (default for Slack): per-thread sessions, all replies in threads
false: per-channel sessions, replies in channel (current behavior for other connectors)
This would also make it easier to roll out thread support gradually on other platforms.
Implementation order
- Mattermost -- closest to Slack, reuse most of the pattern
- Discord -- needs research into ThreadChannel behavior
- Matrix -- needs testing with real clients
Related
- Slack implementation: commits on
feat/thread-isolation
- Base infrastructure (dedup, query guard, expiry): already in
connector-base.ts
- All connectors already opt into the base features
Context
We implemented per-thread session isolation for Slack in the
feat/thread-isolationbranch. Each Slack thread gets its own OpenCode session, and users can continue chatting in a thread without re-mentioning the bot.Three other platforms also support threads:
Mattermost (straightforward)
Mattermost threads work very similarly to Slack. The REST API
POST /api/v4/postsaccepts aroot_idfield to reply in a thread. The WebSocketpostedevent includesroot_idwhen a message is a thread reply.Implementation would closely mirror the Slack approach:
channelId:rootIdroot_idon all outgoing postshandlePostedEvent) already receivespost.root_idDiscord (different model)
Discord threads are actually separate channels (
ThreadChannel). The bot needs to:threadCreateeventsparentIdpointing to the parent channelThis is architecturally different from Slack/Mattermost. The current per-channel session key might already provide some isolation since thread channels have unique IDs. Needs investigation into whether the bot receives thread messages with current intents.
Matrix (newer spec)
Matrix added threads in spec v1.4 (MSC3440) via
m.threadrelations. Thematrix-bot-sdksupports them. Thread replies include am.relates_tofield withrel_type: "m.thread"andevent_idpointing to the thread root.Client support varies -- Element supports threads well, but some clients show them as flat messages. Worth implementing but should be tested with real Matrix clients.
WhatsApp
No thread concept. Skip.
Design note: configurable vs always-on
Currently the Slack implementation is hardcoded to ALWAYS reply in threads. There is no config option to fall back to channel-level replies.
We should consider adding a config flag (e.g.,
threadIsolation: true/falseinchat-bridge.json) so users can choose:true(default for Slack): per-thread sessions, all replies in threadsfalse: per-channel sessions, replies in channel (current behavior for other connectors)This would also make it easier to roll out thread support gradually on other platforms.
Implementation order
Related
feat/thread-isolationconnector-base.ts