Skip to content

Thread isolation for Mattermost, Discord, and Matrix #13

@ominiverdi

Description

@ominiverdi

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

  1. Mattermost -- closest to Slack, reuse most of the pattern
  2. Discord -- needs research into ThreadChannel behavior
  3. 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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions