Hello, We've got a discussion about thread on xsf@ a couple of days ago, and I would like to bring it here. I initially thought that XEP-0461 (Message Replies) was redundant with threads, except in the case where there is no thread ID in the message a user wants to reply too. After discussion, notably with singpolyma and lovetox, it appears that we don't have the same view on this. The way I got it, we have basically 2 ways to see threads: 1. A series of replies to any message in a group chat, à la Slack (in Slack, you see the replies hidden under parent message, with something like "X replies", and when you click, a panel appear with the whole thread. 2. A side discussion explicitly started, that could be seen like a new chat window (UI example: user clicks a "start a new thread button", and start a blank window with it message, this message has a new thread ID, that will be used by people replying to it). In case 1, the parent message needs a thread ID so that thread can continue with the same ID. Problem is if parent message doesn't has a thread ID (because client doesn't support thread, or because there is no thread ID for each message), in this case a XEP-0461 "reply to" can be used, then the first reply has a new thread ID, and the thread can continue. In case 2, the explicitly started thread has a newly generated thread ID, so there is no problem. I want to support both 1 and 2. For 1, my initial reading of XEP-0201 (Best Practices for Message Threads) was that a new thread ID should be generated for each message:
Unless a <message/> stanza is written in direct reply to another <message/> stanza, if a ThreadID is included then its value SHOULD be newly generated when a human user initiates a chat conversation with another user (i.e., a <message/> stanza of type 'chat'), starts a new conversation in the context of a multi-user chat environment (i.e., a <message/> stanza of type 'groupchat'), or sends a normal message. XEP-0201 §3.2.
But after discussion, I realise that it's not requested to generate a new ID each time, and it seems that generating new thread ID for each message would be a problem for some clients (notably Cheogram which would create a thread UI for each ID). The solution would be to use "reply to" from XEP-0461, then a newly generated thread ID. I've also proposed an alternative when parent message ID could be used as thread ID, this may we can find parent message without relying on XEP-0461. For the moment, I think that I won't generate new thread ID for each message, and if I create a thread from a parent message I'll use a XEP-0461 "reply to" and generate a new thread ID, then use this thread ID for following message in this thread. However, I would like to have feedback from the wider community: - how to you handle or plan to handle threads? - Are you planning to implement case 1 (threads can be started from any message) and/or case 2 (threads are explicitly started)? - How would you handle case 1? Thanks! Best, Goffi
Hi, The one thing that bugs me about the reply method is, that it depends on that i go searching first if someone else has replied to be able to send a message. This leads to the situation that multiple threads are created if different people answer nearly at the same time. At this point its unclear how to go forward. Certainly the two people didn't want to have separate threads. Further stuff like moderate can remove all content from a message, it would destroy the link to the parent message if the first reply gets moderated. Leaving all other messages hanging in the air without context. So for me the thread string needs to be generated out of the parent message to avoid this, and also make it simple. If for some reason the community deems it absolute necessary to create threads from messages that don't have a thread themself s, i would simply take the message-id of the parent message and use it as a thread id, circumventing any mentioned problems above. This is even moderate safe, because the message-id is never moderated. This comes at the cost of losing the feature to signal that a message should not be used for a thread. Regards Philipp On Sat, Apr 26, 2025, at 11:24, Goffi wrote:
Hello,
We've got a discussion about thread on xsf@ a couple of days ago, and I would like to bring it here.
I initially thought that XEP-0461 (Message Replies) was redundant with threads, except in the case where there is no thread ID in the message a user wants to reply too. After discussion, notably with singpolyma and lovetox, it appears that we don't have the same view on this.
The way I got it, we have basically 2 ways to see threads:
1. A series of replies to any message in a group chat, à la Slack (in Slack, you see the replies hidden under parent message, with something like "X replies", and when you click, a panel appear with the whole thread.
2. A side discussion explicitly started, that could be seen like a new chat window (UI example: user clicks a "start a new thread button", and start a blank window with it message, this message has a new thread ID, that will be used by people replying to it).
In case 1, the parent message needs a thread ID so that thread can continue with the same ID. Problem is if parent message doesn't has a thread ID (because client doesn't support thread, or because there is no thread ID for each message), in this case a XEP-0461 "reply to" can be used, then the first reply has a new thread ID, and the thread can continue.
In case 2, the explicitly started thread has a newly generated thread ID, so there is no problem.
I want to support both 1 and 2. For 1, my initial reading of XEP-0201 (Best Practices for Message Threads) was that a new thread ID should be generated for each message:
Unless a <message/> stanza is written in direct reply to another <message/> stanza, if a ThreadID is included then its value SHOULD be newly generated when a human user initiates a chat conversation with another user (i.e., a <message/> stanza of type 'chat'), starts a new conversation in the context of a multi-user chat environment (i.e., a <message/> stanza of type 'groupchat'), or sends a normal message. XEP-0201 §3.2.
But after discussion, I realise that it's not requested to generate a new ID each time, and it seems that generating new thread ID for each message would be a problem for some clients (notably Cheogram which would create a thread UI for each ID).
The solution would be to use "reply to" from XEP-0461, then a newly generated thread ID. I've also proposed an alternative when parent message ID could be used as thread ID, this may we can find parent message without relying on XEP-0461.
For the moment, I think that I won't generate new thread ID for each message, and if I create a thread from a parent message I'll use a XEP-0461 "reply to" and generate a new thread ID, then use this thread ID for following message in this thread.
However, I would like to have feedback from the wider community: - how to you handle or plan to handle threads? - Are you planning to implement case 1 (threads can be started from any message) and/or case 2 (threads are explicitly started)? - How would you handle case 1?
Thanks!
Best, Goffi _______________________________________________ Standards mailing list -- standards@xmpp.org To unsubscribe send an email to standards-leave@xmpp.org
*Attachments:* • signature.asc
Hi Philipp, thanks for your feedback. Le samedi 26 avril 2025, 12:26:47 heure d’été d’Europe centrale Philipp Hörist a écrit :
The one thing that bugs me about the reply method is, that it depends on that i go searching first if someone else has replied to be able to send a message.
This leads to the situation that multiple threads are created if different people answer nearly at the same time. At this point its unclear how to go forward. Certainly the two people didn't want to have separate threads.
I don't see that it's needed to check for other replies. If two people start a reply at the same time, there will be two threads with the same parent, in the UI this appears like a tree, i stays readable. This is what happens on sites like Reddit on ActivityPub (but on Mastodon, the tree doesn't appear in comments, making it very confusing IMO).
Further stuff like moderate can remove all content from a message, it would destroy the link to the parent message if the first reply gets moderated. Leaving all other messages hanging in the air without context.
Indeed, that's a problem if the first reply with the new thread ID is deleted, good point.
So for me the thread string needs to be generated out of the parent message to avoid this, and also make it simple.
If for some reason the community deems it absolute necessary to create threads from messages that don't have a thread themself s, i would simply take the message-id of the parent message and use it as a thread id, circumventing any mentioned problems above. This is even moderate safe, because the message- id is never moderated.
Yeah, that's the alternative that I have proposed. I think that using parent message ID as thread ID is a good option, maybe with a XEP to explain this behaviour. This can be used at the same time as XEP-0461, so clients implementing only XEP-0461 can still see it as a reply (but XEP-0461 says that it should not be used for sub-thread, so if other replies are made using XEP-0461, it may be a problem).
This comes at the cost of losing the feature to signal that a message should not be used for a thread.
How do you signal that a message should not be used for a thread, and why would you do that? From a UX point of view, I think that it would be bad that some messages can be replied in a thread, and some other can't, the end-user would not understand why sometime the button appears, and sometimes not. Best, Goffi
[sorry my previous message was badly formatted, I send it again to make it more readable] Hi Philipp, thanks for your feedback. Le samedi 26 avril 2025, 12:26:47 heure d’été d’Europe centrale Philipp Hörist a écrit :
The one thing that bugs me about the reply method is, that it depends on that i go searching first if someone else has replied to be able to send a message.
This leads to the situation that multiple threads are created if different people answer nearly at the same time. At this point its unclear how to go forward. Certainly the two people didn't want to have separate threads.
I don't see that it's needed to check for other replies. If two people start a reply at the same time, there will be two threads with the same parent, in the UI this appears like a tree, i stays readable. This is what happens on sites like Reddit on ActivityPub (but on Mastodon, the tree doesn't appear in comments, making it very confusing IMO).
Further stuff like moderate can remove all content from a message, it would destroy the link to the parent message if the first reply gets moderated. Leaving all other messages hanging in the air without context.
Indeed, that's a problem if the first reply with the new thread ID is deleted, good point.
So for me the thread string needs to be generated out of the parent message to avoid this, and also make it simple.
If for some reason the community deems it absolute necessary to create threads from messages that don't have a thread themself s, i would simply take the message-id of the parent message and use it as a thread id, circumventing any mentioned problems above. This is even moderate safe, because the message- id is never moderated.
Yeah, that's the alternative that I have proposed. I think that using parent message ID as thread ID is a good option, maybe with a XEP to explain this behaviour. This can be used at the same time as XEP-0461, so clients implementing only XEP-0461 can still see it as a reply (but XEP-0461 says that it should not be used for sub-thread, so if other replies are made using XEP-0461, it may be a problem).
This comes at the cost of losing the feature to signal that a message should not be used for a thread.
How do you signal that a message should not be used for a thread, and why would you do that? From a UX point of view, I think that it would be bad that some messages can be replied in a thread, and some other can't, the end-user would not understand why sometime the button appears, and sometimes not. Best, Goffi
Hi, On Sat, Apr 26, 2025, at 12:57, Goffi wrote:
I don't see that it's needed to check for other replies. If two people start a reply at the same time, there will be two threads with the same parent, in the UI this appears like a tree, i stays readable. This is what happens on sites like Reddit on ActivityPub (but on Mastodon, the tree doesn't appear in comments, making it very confusing IMO).
Never used those services, but the normal flow i imagine is, im in a support channel, someone asks a question "How do i do X?", now 2 people start to type, and create two separate threads with the answer, now a 4. person wants to join, then the client needs to decide to reply to one of the threads. Also from the GUI side its unclear how should handle this, should i hide the fact that there are 2 threads? Should i show 2 threads? But then obviously both users wanted to answer the same person, i would say it would be the expectation that this conversation is wrapped in a single thread and not multiple. But maybe i envision this worse than it is in practice.
This comes at the cost of losing the feature to signal that a message should not be used for a thread.
How do you signal that a message should not be used for a thread, and why would you do that?
From a UX point of view, I think that it would be bad that some messages can be replied in a thread, and some other can't, the end-user would not understand why sometime the button appears, and sometimes not.
I just wanted to note what the implications are of the design decision. I could imagine someone wanting in their channel that no thread is created under a bot message. I dont see this as a show stopper, just want to prevent that in a year we need to add <no-thread> for some reason, when we could have it now naturally by not including a thread. As for the moderation XEP, i definitely think the moderation and als retraction XEP should exclude the <thread> element from being removed, from the message. Regards Philipp
Hi, Adding a few design notes from my experience with other platforms. Hopefully this will help inform further discussion.
I don't see that it's needed to check for other replies. If two people start a reply at the same time, there will be two threads with the same parent, in the UI this appears like a tree, i stays readable. This is what happens on sites like Reddit on ActivityPub (but on Mastodon, the tree doesn't appear in comments, making it very confusing IMO).
ActivityPub uses the concept of "parent post" rather than "threads". And yes, it does get confusing when the replies branch out into a tree and then get "flattened" out for display in interfaces like Mastodon's. If I want to choose a single strand of the conversation, I would choose the last post in that sequence, and then get presented with all direct ancestors of that post (which is a single strand as each child can only have one parent). I think this "single linear sequence, among possibly many", is what originally became Twitter-style "threads" (now used by Mastodon too). In summary: AP "threads" are basically "a sequence of posts where each post is a child of the immediately preceding one", but as each original post can branch out into many "threads" I'd say it's more of a GUI consideration than anything else.
Never used those services, but the normal flow i imagine is, im in a support channel, someone asks a question "How do i do X?", now 2 people start to type, and create two separate threads with the answer, now a 4. person wants to join, then the client needs to decide to reply to one of the threads.
Also from the GUI side its unclear how should handle this, should i hide the fact that there are 2 threads? Should i show 2 threads? But then obviously both users wanted to answer the same person, i would say it would be the expectation that this conversation is wrapped in a single thread and not multiple.
What happens in AP in practice is that the third commenter would make another reply that is a direct child of the original post (yet another "thread" if you will). People also use it in this way; if I wanted to reply specifically to Commenter 1 I would reply to Commenter 1's post, but if I wanted to make a general comment on the entire conversation I would reply directly to the main thread. This is very different from how I would approach interacting with a conversation in a chat-oriented app (XMPP or otherwise): on ActivityPub I'm more diligent about selecting the specific message I want to reply to. I think that's partly because each reply is a "post" in its own right that could be shared, boosted, etc. and show up on peoples' timelines as an entry point to whatever they're going to see next. Depending on which message I reply to, they'd be presented with a different view of the conversation (which they could change, of course, but it is their first view of the entire conversation). Finally, with regard to moderation/retraction: with ActivityPub software (including Akkoma and Mastodon), when I'm deleting a post I get a warning that any replies to that post will be "orphaned", i.e. not have a parent any more. I have also seen some posts where in place of a parent all I get is "this post no longer exists". So it is arguably an issue there as well (but see my next section with thoughts about threads). ------------------------------------------------------------------------ On a different note, since there was some debate about how to include thread IDs: Discord, unlike AP, treats "threads" and "a sequence of replies" as two different things. The default mode is to have all the conversation inline (no threads/parents/etc.) but if there's a sequence of replies (a message, to which there is a reply, to which there is another reply) then it asks if I want to "convert that message to a thread". (One can decide to make a message into a thread at any point, but the UX explicitly suggests it when it thinks a sequence of replies has gone on for long enough) At that point, only the parent message will be shown in the main message area and subsequent replies (which are all linear/sequential) show up only when you click on that parent message to navigate into the thread. Mattermost, on the other hand, does "both" which I suppose is somewhat similar to Mastodon. Replies are internally a "tree of replies", but the default view is to show only the first message and make the user click through to see the other replies in a linear way (so, visually similar to Discord "threads"). However, there is also an option to turn off "threads mode" at which point all the child replies will show up along with the main messages (visually similar to Discord "replies"). In this mode clicking on any of the child messages will show up the entire "thread" (i.e. initial parent message and all it's descendant replies). In my opinion Mattermost is the most confusing as people experience the messages differently depending on their settings. For XMPP, perhaps we should first decide which of "linear threads" or "branching-out replies" is being defined? Even if we have both, in my opinion it would be better to treat them as separate (if somewhat related) concepts. Linear threads would be the ones with thread IDs whereas "branching out replies" don't need to have anything to do with threads at all. After typing the above, I realised that Goffi had outlined these different modes of thinking too; I am pasting a quote for reference:
The way I got it, we have basically 2 ways to see threads:
1. A series of replies to any message in a group chat, à la Slack (in Slack, you see the replies hidden under parent message, with something like "X replies", and when you click, a panel appear with the whole thread.
2. A side discussion explicitly started, that could be seen like a new chat window (UI example: user clicks a "start a new thread button", and start a blank window with it message, this message has a new thread ID, that will be used by people replying to it). As I said, I think it would be best to treat these as two separate features, and either decide which we want or do as Discord does and offer each as distinct options.
Best, Badri
Thanks for your post it's interesting to see how things are handled across software. Just a side note: whatever we choose, we have to consider gateways. Somehow somebody will have to convert third party network behaviour to XMPP one. So I'm in favor of some flexibility. The challenge is to have it while keeping UX acceptable, and not confusing when we switch XMPP client. Le 27 avril 2025 09:26:46 GMT+02:00, Badri Sunderarajan <badrihippo@disroot.org> a écrit :
Hi,
Adding a few design notes from my experience with other platforms. Hopefully this will help inform further discussion.
I don't see that it's needed to check for other replies. If two people start a reply at the same time, there will be two threads with the same parent, in the UI this appears like a tree, i stays readable. This is what happens on sites like Reddit on ActivityPub (but on Mastodon, the tree doesn't appear in comments, making it very confusing IMO).
ActivityPub uses the concept of "parent post" rather than "threads". And yes, it does get confusing when the replies branch out into a tree and then get "flattened" out for display in interfaces like Mastodon's.
If I want to choose a single strand of the conversation, I would choose the last post in that sequence, and then get presented with all direct ancestors of that post (which is a single strand as each child can only have one parent). I think this "single linear sequence, among possibly many", is what originally became Twitter-style "threads" (now used by Mastodon too).
In summary: AP "threads" are basically "a sequence of posts where each post is a child of the immediately preceding one", but as each original post can branch out into many "threads" I'd say it's more of a GUI consideration than anything else.
Never used those services, but the normal flow i imagine is, im in a support channel, someone asks a question "How do i do X?", now 2 people start to type, and create two separate threads with the answer, now a 4. person wants to join, then the client needs to decide to reply to one of the threads.
Also from the GUI side its unclear how should handle this, should i hide the fact that there are 2 threads? Should i show 2 threads? But then obviously both users wanted to answer the same person, i would say it would be the expectation that this conversation is wrapped in a single thread and not multiple.
What happens in AP in practice is that the third commenter would make another reply that is a direct child of the original post (yet another "thread" if you will). People also use it in this way; if I wanted to reply specifically to Commenter 1 I would reply to Commenter 1's post, but if I wanted to make a general comment on the entire conversation I would reply directly to the main thread.
This is very different from how I would approach interacting with a conversation in a chat-oriented app (XMPP or otherwise): on ActivityPub I'm more diligent about selecting the specific message I want to reply to. I think that's partly because each reply is a "post" in its own right that could be shared, boosted, etc. and show up on peoples' timelines as an entry point to whatever they're going to see next. Depending on which message I reply to, they'd be presented with a different view of the conversation (which they could change, of course, but it is their first view of the entire conversation).
Finally, with regard to moderation/retraction: with ActivityPub software (including Akkoma and Mastodon), when I'm deleting a post I get a warning that any replies to that post will be "orphaned", i.e. not have a parent any more. I have also seen some posts where in place of a parent all I get is "this post no longer exists". So it is arguably an issue there as well (but see my next section with thoughts about threads).
------------------------------------------------------------------------
On a different note, since there was some debate about how to include thread IDs: Discord, unlike AP, treats "threads" and "a sequence of replies" as two different things. The default mode is to have all the conversation inline (no threads/parents/etc.) but if there's a sequence of replies (a message, to which there is a reply, to which there is another reply) then it asks if I want to "convert that message to a thread". (One can decide to make a message into a thread at any point, but the UX explicitly suggests it when it thinks a sequence of replies has gone on for long enough)
At that point, only the parent message will be shown in the main message area and subsequent replies (which are all linear/sequential) show up only when you click on that parent message to navigate into the thread.
Mattermost, on the other hand, does "both" which I suppose is somewhat similar to Mastodon. Replies are internally a "tree of replies", but the default view is to show only the first message and make the user click through to see the other replies in a linear way (so, visually similar to Discord "threads").
However, there is also an option to turn off "threads mode" at which point all the child replies will show up along with the main messages (visually similar to Discord "replies"). In this mode clicking on any of the child messages will show up the entire "thread" (i.e. initial parent message and all it's descendant replies).
In my opinion Mattermost is the most confusing as people experience the messages differently depending on their settings. For XMPP, perhaps we should first decide which of "linear threads" or "branching-out replies" is being defined? Even if we have both, in my opinion it would be better to treat them as separate (if somewhat related) concepts. Linear threads would be the ones with thread IDs whereas "branching out replies" don't need to have anything to do with threads at all.
After typing the above, I realised that Goffi had outlined these different modes of thinking too; I am pasting a quote for reference:
The way I got it, we have basically 2 ways to see threads:
1. A series of replies to any message in a group chat, à la Slack (in Slack, you see the replies hidden under parent message, with something like "X replies", and when you click, a panel appear with the whole thread.
2. A side discussion explicitly started, that could be seen like a new chat window (UI example: user clicks a "start a new thread button", and start a blank window with it message, this message has a new thread ID, that will be used by people replying to it). As I said, I think it would be best to treat these as two separate features, and either decide which we want or do as Discord does and offer each as distinct options.
Best, Badri
Hi, On Sat, 2025-04-26 at 12:57 +0200, Goffi wrote:
but XEP-0461 says that it should not be used for sub-thread, so if other replies are made using XEP-0461, it may be a problem
To clarify on this: XEP-0461 was meant to be used exclusively for replying to a message, not to indicate any thread logic or anything similar. Replies are meant to show in the "main" timeline (not a sub-thread) and two replies to the same message are not meant to have any direct relation with each other. The purpose of XEP-0461 was to clean-up/standardize on something that was done in the wild: Users (and some clients) used "quote reply" to a message, meaning to copy the entire contents of a previous message as a blockquote in a new message and then write below that, indicating this is a reply to that previous message. XEP-0461 allows to do that in a way that is understood properly by clients (allowing to link to the original message or show extra details about the original message). It also makes it possible to extend this functionality to non-textual message (file share). In other words, XEP-0461 is the equivalent of the reply feature you can see in WhatsApp or Telegram and is completely adjacent to threads in the style of Slack, Zulip or Cheogram. Marvin
On 2025-04-26 12:26, Philipp Hörist wrote:
If for some reason the community deems it absolute necessary to create threads from messages that don't have a thread themself s, i would simply take the message-id of the parent message and use it as a thread id, circumventing any mentioned problems above. This is even moderate safe, because the message-id is never moderated. This comes at the cost of losing the feature to signal that a message should not be used for a thread.
While I don't have any preference for one or the other solution, the latter could be signalled explicitely. Might need a new XEP, though. On Sat, Apr 26, 2025, at 11:24, Goffi wrote:
2. A side discussion explicitly started, that could be seen like a new chat window (UI example: user clicks a "start a new thread button", and start a blank window with it message, this message has a new thread ID, that will be used by people replying to it).
In my experience, this is not how humans work. People will just reply, and not care about any change of subject. That's what is happening with email all of the time :-( Cheers
participants (5)
-
Badri Sunderarajan -
Goffi -
Martin -
Marvin W -
Philipp Hörist