fix(gateway): always prefix non-DM messages with sender name - #80235
Closed
Wintle wants to merge 1 commit into
Closed
fix(gateway): always prefix non-DM messages with sender name#80235Wintle wants to merge 1 commit into
Wintle wants to merge 1 commit into
Conversation
Wintle
force-pushed
the
fix/sender-prefix-decoupled-from-session-isolation
branch
from
August 6, 2026 10:31
116279f to
9ec378b
Compare
The LLM never saw a sender attribution on group/thread messages under
the default ``group_sessions_per_user=True`` config. The prefix code in
``GatewayRunner._prepare_inbound_message_text`` only fired when
``is_shared_multi_user_session(source)`` was True, and that predicate is
False by default — session keys isolate per-participant, so the LLM saw
plain text without any ``[user_name]`` prefix.
Decouple the two concerns
-------------------------
``is_shared_multi_user_session`` describes **session-key isolation**
(whether multiple participants share the same conversation history).
The sender prefix describes **message attribution** (whether the LLM
can tell who sent the current message). Those are independent questions
and conflating them was the bug.
New predicate ``_should_prefix_sender``::
source.chat_type != "dm" and bool(source.user_name)
Prefix every non-DM inbound (group + thread), regardless of
``group_sessions_per_user`` / ``thread_sessions_per_user`` config.
DMs keep the existing 1:1 contract — no prefix.
Backward compatibility
----------------------
- ``_is_shared_multi_user`` is still computed at the top of the block
(kept as a named local so any future consumer in the same scope that
expects it does not break). It is no longer used for the prefix
decision.
- DM messages: identical behaviour to before (no prefix).
- Group/thread with non-shared sessions: **NEW** — prefix now fires.
The previous behaviour was a latent bug; if a downstream caller
depended on the absence of a prefix on isolated group sessions it
was depending on a bug.
- ``source.user_name`` None / empty: no prefix (same as before).
- Hostile display names containing newlines or control chars: still
neutralized via ``neutralize_untrusted_inline_text`` before
interpolation (same defence that already existed for shared sessions).
Tests
-----
``tests/gateway/test_sender_prefix_decoupling.py`` (new, 6 tests):
- group message under default isolation gets prefix (the bug)
- thread message gets prefix
- DM message never gets prefix
- ``user_name=None`` does not produce literal "[None]"
- hostile name with embedded newline is neutralized
- prefix is independent of session-isolation config
RED on origin/main: 3 failed, 3 passed
GREEN with this fix: 6 passed
Sibling matrix + session tests: all green.
Related
-------
- NousResearch#80206 (PR 1): MessageEvent gains user_id/user_name fields.
- NousResearch#80211 (PR 3): phantom intake filter that breaks the self-loop.
- This PR (NousResearch#2): makes the prefix actually fire so the LLM can read
the sender field PR NousResearch#1 added. Together these three form the
minimal fix surface for the orphan-intake-notice issue.
Files changed
-------------
- gateway/run.py: ``_prepare_inbound_message_text`` ~L15776 —
replace ``if _is_shared_multi_user and source.user_name:`` with
``if _should_prefix_sender:`` plus block comment explaining the
decoupling.
- tests/gateway/test_sender_prefix_decoupling.py (new) — 6 tests,
~195 lines.
Wintle
force-pushed
the
fix/sender-prefix-decoupled-from-session-isolation
branch
from
August 6, 2026 10:33
9ec378b to
e80878a
Compare
13 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The LLM never saw sender attribution on group / thread messages under the
default
group_sessions_per_user=Trueconfig. The prefix code inGatewayRunner._prepare_inbound_message_textonly fired whenis_shared_multi_user_session(source)was True, and that predicate isFalse by default — session keys isolate per-participant, so the LLM saw
plain text without any
[user_name]prefix.Decouple the two concerns
is_shared_multi_user_sessiondescribes session-key isolation (whethermultiple participants share the same conversation history). The sender
prefix describes message attribution (whether the LLM can tell who
sent the current message). Those are independent questions and conflating
them was the bug.
New predicate
_should_prefix_sender:Prefix every non-DM inbound (group + thread), regardless of
group_sessions_per_user/thread_sessions_per_userconfig. DMs keepthe existing 1:1 contract — no prefix.
Backward compatibility
_is_shared_multi_useris still computed at the top of the block (keptas a named local so any future consumer in the same scope that expects
it does not break). It is no longer used for the prefix decision.
The previous behaviour was a latent bug; if a downstream caller depended
on the absence of a prefix on isolated group sessions it was depending
on a bug.
source.user_nameNone / empty: no prefix (same as before).neutralized via
neutralize_untrusted_inline_textbefore interpolation(same defence that already existed for shared sessions).
Tests
tests/gateway/test_sender_prefix_decoupling.py(new, 6 tests):user_name=Nonedoes not produce a prefix<@U...>user id next to the displayname (existing behaviour preserved)
Verification
RED on origin/main (stashed source fix, kept tests):
GREEN after fix (popped stash):
Sibling regression (
test_internal_event_never_interrupts_busy_session.pyand other gateway tests that exercise
_prepare_inbound_message_text):all green.
Files changed
gateway/run.py— new module-level helper_should_prefix_sender(source);_prepare_inbound_message_textuses it instead of theis_shared_multi_usergate.
_is_shared_multi_userlocal kept for backward compat (stillcomputed, no longer consulted for prefixing).
tests/gateway/test_sender_prefix_decoupling.py(new) — 6 invariant testspinning the prefix-on-group / no-prefix-on-DM / neutralization contract.
Bot / duplicate check
addresses the same root-cause surface area from the message-event side;
not a duplicate, both stand alone)