How Telegram's Reply Threading Default Quietly Broke DM UX

I was debugging a strange UX regression in OpenClaw when I realized something subtle was happening in our Telegram integration. Every single response to a direct message was being rendered as a quoted reply—those nested message bubbles that make sense in group chats but feel noisy in 1:1 conversations.
The culprit? A perfect storm of timing and defaults.
Back in version 2026.2.13, the team shipped implicit reply threading—a genuinely useful feature that automatically threads responses back to the original message. On its own, this is great. But we had an existing default setting that nobody had really questioned: replyToMode was set to "first", meaning the first message in every response would be sent as a native Telegram reply.
Before 2026.2.13, this default was mostly invisible. Reply threading was inconsistent, so the "first" mode rarely produced visible quote bubbles in practice. Users didn’t notice because the threading engine wasn’t reliable enough to actually use it. But once implicit threading started working reliably, that innocent default suddenly meant every DM response got wrapped in a quoted message bubble. A simple “Hi” → “Hey” exchange turned into a noisy back-and-forth of nested quotes.
It’s a classic case of how API defaults compound unexpectedly when underlying behavior changes. The default itself wasn’t wrong—it was designed for a different technical landscape.
The fix was straightforward: change the default from "first" to "off". This restores the pre-2026.2.13 experience for DM conversations. Users who genuinely want reply threading in their workflow can still opt in explicitly:
channels.telegram.replyToMode: "first" | "all"
I tested the change on a live 2026.2.13 instance by toggling the setting. With "first" enabled, every response quoted the user’s message. Flip it to "off", and responses flow cleanly without the quote bubbles. The threading infrastructure still works—it’s just not forced into every conversation by default.
No test code needed updating because our test suite was already explicit about replyToMode, never relying on defaults. That’s a small win for test maintainability.
The lesson here: defaults are powerful exactly because they’re invisible. When a feature’s behavior changes—especially something foundational like message threading—revisit the defaults that interact with it. Sometimes the most impactful fix isn’t adding new logic, it’s changing what happens when you don’t specify anything.
Also, a programmer once put two glasses on his bedside table before sleep: one full in case he got thirsty, one empty in case he didn’t. Same energy as choosing "off" by default and letting users opt in—sometimes the simplest choice is the wisest 😄
Metadata
- Branch:
- main
- Dev Joke
- Чем отличается машинный код от бессмыслицы? Машинный код работает