fix(gateway): skip sender prefix for internal events + NO_REPLY contract in async delegation (#66480) - #66507
Conversation
|
Thanks for the focused regression fix. Current The proposed changes address those exact paths, and |
651914d to
7934004
Compare
SummaryFive PRs address or reference two related sender-context issues: #18711 exposes the verified current Slack author mention, #66507 prevents internal-event impersonation and suppresses redundant async follow-ups, #67886 repairs sender-prefix ordering, #13939 broadens ID-qualified attribution, and #44705 labels unnamed shared-session participants. The attribution PRs overlap in gateway code but target distinct causes and have documented salvage requirements. Related pull requests
DuplicatesNo listed PRs are exact duplicates: #13939 and #44705 overlap on sender attribution, while #67886 changes ordering in the same path but fixes a separate enrichment bug; #18711 is the closed source implementation integrated through #69320, and #66507 addresses the separate internal-event and async-completion causes. Suggested consolidationKeep #66507 open with its focused salvage path for #66480. Keep #67886 open with a salvage path that rebases the ordering change onto current main, preserves the Slack mention augmentation, and adds the requested regression; author action for #13939 is to rebase or split out viable attribution work after resolving the contributor findings, and author action for #44705 is to split the participant-labeling fix from unrelated hunks and add the Yuanbao no-double-prefix guard. Leave #18711 closed because its implementation was integrated via #69320; the evidence does not support closing any remaining listed PR as an exact duplicate. Complex graphflowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
I66480(["issue #66480 (open)"])
P66507["PR #66507 (open)"]
P66507 -->|best fix| I66480
class I66480 open
class P66507 open
class P66507 best
class P66507 target
click I66480 "https://github.com/NousResearch/hermes-agent/issues/66480"
click P66507 "https://github.com/NousResearch/hermes-agent/pull/66507"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label). Cross-PR triage: Reviewed 5 pull requests and 2 issues in this complex. Each diff was read against this issue; Assessment working set: 42 kB of PR diffs, 18 kB of issue/PR text, 9 kB of discussion (10 comments), 6 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
|
Independent real-world verification on Hermes Agent v0.20.2 and the current
This confirms that the I independently validated an equivalent minimal change against the current tree:
One wording hardening may help in practice:
The affected agent already had a general user preference to absorb unchanged late reviews silently, but still generated an acknowledgement. Making the prohibition explicit in the completion envelope reduces that ambiguity. I did not open a duplicate PR. This branch is currently reported as |
What
In shared multi-user gateway sessions, async-delegation completions injected via
_inject_watch_notificationimpersonated the originating user:_prepare_inbound_message_text()applied the[user_name]sender prefix to all messages, including internal synthetic events. The parent then saw text shaped like[Alice] [ASYNC DELEGATION BATCH COMPLETE …]even though Alice sent nothing.Separately, the async-delegation completion formatter told the agent to "act on the result or re-dispatch", but never told it to suppress a redundant reply when the result did not materially change an already-delivered answer. The gateway already supports suppressing a turn whose exact response is
NO_REPLY(seegateway/response_filters.py), but the completion prompt never invoked that contract.Closes #66480.
How
Two focused changes, both covering the full bug class:
Sender prefix bypass for internal events —
gateway/run.py: the shared-session prefix condition gainsand not event.internal, so internal synthetic events (async delegation completions, which carry the originatingSessionSourcebut are markedinternal=True) skip the[user_name]prefix.MessageEvent.internaldefaults toFalse, so normal messages are unaffected.NO_REPLYno-news contract in BOTH completion formatters —tools/process_registry.py:_format_async_delegation()now appends:to both the single and the batch (fan-out) completion headers, so a no-news completion no longer triggers a redundant user-facing reply while still surfacing material updates/corrections.
Verification
Reproduced on current
mainbefore the fix; both symptoms gone after.TDD red→green, run against the shared venv Python (
Python 3.11.15):tests/gateway/test_shared_group_sender_prefix.py::test_internal_event_skips_sender_prefix_in_shared_session— fails onmain(output was[Alice] [ASYNC …]), passes after fix.tests/tools/test_async_delegation.py::test_async_delegation_formatter_includes_no_reply_contract— fails onmain(noNO_REPLYin single output), passes after fix.tests/tools/test_async_delegation.py::test_batch_async_delegation_formatter_includes_no_reply_contract— fails onmain(noNO_REPLYin batch output), passes after fix. The issue requires the contract in both single and batch formatters.Existing invariants preserved:
test_preprocess_prefixes_sender_for_shared_non_thread_group_session— normal shared message still becomes[Alice] hello.test_preprocess_keeps_plain_text_for_default_group_sessions— default group sessions still get plain text.Full focused suite after rebase onto
main(7f76fc040):167 passed, 0 failedacrosstests/tools/test_async_delegation.py,tests/gateway/test_shared_group_sender_prefix.py,tests/tools/test_process_registry.py,tests/gateway/test_completion_delivery.py,tests/gateway/test_async_delegation_session_binding.py,tests/gateway/test_internal_event_never_interrupts_busy_session.py.Branch is one focused commit ahead of
main(0 1);git diff --checkclean.Competitor analysis
No competing open PRs found for
#66480(targeted search by issue number, branch-name pattern, and keywords).Auto-published by Moonsong via Path B automated pipeline.