镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Threaded replies omit the NIP-10 p tag for the parent author — replying to someone never notifies them #3032

Open

Description

@shani-singh1

Summary

A threaded reply carries NIP-10 e tags (root/reply markers) but no p tag for the author being replied to. Buzz notifications are #p-based, so replying to someone in a thread never notifies them unless you also type their @name. In a thread you are, by definition, replying to a specific person — they should be notified.

This is the same class as #2568 (reactions dropped the p tag); @vitorpamplona flagged it as a follow-up on that PR. NIP-10 says a reply's p tags SHOULD list the pubkeys being replied to; Buzz emits the e markers but omits the matching p.

Confirmed on main @ 499c5d34.

Where the p tag is dropped

Every reply builder emits e tags for threading but sources p tags only from explicit @mentions:

  • SDK — crates/buzz-sdk/src/builders.rs:173 thread_tags pushes only ["e", …, "reply"] / ["e", …, "root"]. p tags come solely from mention_tags (builders.rs:188), i.e. parsed @mentions. build_message (kind 9) threads these two independently.
  • Desktop — desktop/src-tauri/src/commands/messages.rs:432 resolve_thread_ref already fetches the parent event (to read its root), so parent.pubkey — the signer — is right there, but it is discarded. send_channel_message p-tags only the composer's @mention_pubkeys.
  • Mobile — mobile/lib/features/channels/send_message_provider.dart:56 builds _buildReplyTags (e-tags) plus p tags from normalizedMentions (explicit mentions) only.

Why it's a real notification miss

Notification/feed reads are #p-only, with no fallback that derives the parent author from the reply e-tag:

  • Desktop feed: {"kinds":[9,40002,1,45001,45003],"#p":[self]} (commands/messages.rs).
  • Mobile activity: same kind set, #p:[self] (activity_provider.dart).
  • Push leases advertise kind 9 and subscribe by #p (push_lease.rs).
  • Relay ingest updates thread counters but never injects a p tag or notifies the parent author from the e-tag (grep of ingest.rs/side_effects.rs).

So: no p tag → the replied-to author gets no feed entry and no push.

Reproduce

  1. User A posts a message in a channel.
  2. User B opens the thread on that message and replies without typing @A.
  3. The kind:9 reply carries [["h",…],["e",<root>,"","root"],["e",<A's msg>,"","reply"]] and no ["p", <A>].
  4. User A's mentions feed (#p:[A]) does not include the reply; no push fires.

Expected: A is notified that B replied to them.

Suggested fix

When building a threaded reply, add the parent event's signer as a p tag (deduped against existing mentions, self excluded) — mirroring the fix approach in #2634 (use the signer, not the resolved display author):

  • Desktop: resolve_thread_ref already holds parent.pubkey; thread it into the reply's p tags — no extra query.
  • Mobile: the thread compose bar has the threadHead message; pass its author through.
  • SDK/CLI/ACP: carry the parent author alongside the existing ThreadRef.

Note / product check

This is standard chat behavior (Slack/Discord notify the parent on a thread reply) and NIP-10-conformant, so I'm treating it as a bug. If the team would rather gate reply-notifications behind a preference, say so and I'll adjust — but the p tag being absent from the wire form is a conformance gap regardless.

I have a fix in progress across all surfaces; PR to follow.

Activity

  1. donmcallister58 commented on Jul 28, 2026

    @donmcallister58

    Corroborating this from a live multi-agent deployment (Buzz Desktop 0.4.26, several managed ACP agents). This is the highest-impact instance of the missing p tag in day-to-day use, and it has a specific surface worth adding to the list above:

    The Inbox reply composer. When you reply to an agent's message from the Inbox (not by typing in the channel), the composer does not auto-attach the parent author's p tag, and there is no visible cue that the response tag is missing. The reply posts fine and threads correctly, but the agent is never woken, so the reply is silently dropped. From the user's side it looks like the agent ignored them. The only reliable workaround today is to remember to type @agent and pick from the picker on every reply, which defeats the point of replying from the Inbox.

    Two concrete asks, both consistent with the fix already described:

    1. Derive the p tag from the reply's parent e tag on send, so replying to someone always notifies them (the fix in this issue). The Inbox reply path should be covered alongside send_channel_message.
    2. As a UX safety net, have the Inbox reply composer pre-fill the parent author as a mention chip, so the notify target is visible and editable before sending.

    Related surfaces already filed: #2540 (editing a message to add an @mention does not trigger the agent) and #2270 (agents go deaf in threads unless re-mentioned) are the same root reaching users through different paths.

  2. zannavanderaa commented on Aug 4, 2026

    @zannavanderaa

    Another instance of this on Buzz Desktop 0.5.4 (Windows 11), and it exposes a gap in the fix as currently scoped.

    The comment above covers the Inbox reply composer dropping the parent author's p tag on a threaded reply. Same composer, but in a 1:1 agent DM the reply is not threaded at all, and the published event carries neither p nor e:

    Reply composed from the Inbox, in a DM channel whose only other member is the agent:

    kind: 9
    content: "Done"
    tags: [["h","04050f5d-…"]]
    

    Same user, same channel, same agent, typing into the DM view 38 seconds later:

    kind: 9
    content: "Just did that in Inbox…"
    tags: [["h","04050f5d-…"], ["p","0cf79b97…"], ["imeta", …]]
    

    The Inbox-composed message publishes fine and renders normally in the DM view. The agent is never woken.

    Why this matters for the proposed fix: the suggested remedy is to derive the p tag from the reply's parent e tag. Here there is no e tag to derive from, so that fix would leave this path broken. Two options that would cover it:

    1. In a DM channel, derive the recipient from channel membership when the composer produces no explicit mention. The recipient is unambiguous by construction.
    2. Extend the proposed mention-chip safety net to the DM composer, so the notify target is visible and editable before sending.

    One note on severity. The user-facing shape of this is indistinguishable from an agent that is broken or ignoring you: the message posts, it appears in the conversation, and nothing happens. The reasonable conclusion for a new user is that agents do not work. In this case it took reading raw event tags to establish that the message had been silently dropped rather than ignored, which is not a diagnosis an ordinary user can perform.

    Reported by an agent on this account's Buzz instance, with the account owner's go-ahead.

  3. added 3 commits that reference this issue on Aug 5, 2026
    cd5f6e9
    a2b50ce
    c7bc269
  4. whyihaveyou commented on Aug 7, 2026

    @whyihaveyou

    Confirmed independently from the codebase — this is real, and here's the exact mechanism that makes the Inbox reply path drop the p tag (which the thread above and the two comments reference but don't pin down precisely).

    Why DM-direct works but Inbox-reply doesn't, at the code level:

    • The ACP hook that wakes an agent is require_mention, which matches on a p tag containing the agent pubkey (crates/buzz-acp/src/filter.rs, match_event, step 3). No p tag → agent never wakes.
    • DM direct-compose path (ChannelScreen → useSendMessageMutation): calls messageMentionPubkeys(effectiveChannel, identity.pubkey, mentionPubkeys) (desktop/src/features/messages/lib/messageMentionPubkeys.ts). When channel.channelType === "dm" it expands memberPubkeys + participantPubkeys into the p tags — so the agent is included even with no @mention typed.
    • Inbox reply path (HomeView.onSendReply → sendChannelMessage at desktop/src/features/home/ui/HomeView.tsx): passes the composer's mentionPubkeys straight through to sendChannelMessage without messageMentionPubkeys. So only explicit @agent mentions produce a p tag. Moreover the Inbox MessageComposer (InboxDetailPane) is not given onPrepareSendChannel — the hook ChannelPane passes for DM channels (usePrepareDmSendChannel) to resolve DM recipients — so there is no DM-member expansion at all on this path.

    This matches the raw-event repro in the thread above exactly: Inbox reply in a 1:1 agent DM publishes with tags: [["h",…]] and no p/e; DM compose 38s later carries ["p", agent].

    Recommendation to the fix already in progress: the parent-author fix (derive p from the reply's e tag) fixes threaded replies but, as comment #3 noted, leaves the 1:1 DM Inbox path broken because there is no e tag there. The Inbox reply path likely needs the same DM-recipient expansion that the DM compose path gets — either by routing Inbox replies through messageMentionPubkeys (expanding DM members), or by passing onPrepareSendChannel into the Inbox MessageComposer. I'd suggest covering both threaded and 1:1 DM Inbox replies in this fix.

    Happy to help test once the PR lands.

  5. UnoRazorback commented on Sep 5, 2026

    @UnoRazorback

    Still reproduces on main @ b1f6b7e (2026-09-04) — self-hosted relay, Buzz Desktop from the signed release, five buzz-acp agents in one channel.

    Both reply builders still emit e tags only; p tags come solely from explicit mentions:

    • desktop/src-tauri/src/events.rs:54 thread_tags → ["e", root, "", "root"] / ["e", parent, "", "reply"]. mention_tags (line 67) is the only source of ["p", …], and the two are composed independently.
    • crates/buzz-sdk/src/builders.rs:178 — same shape.

    Captured from a live channel:

    Human reply through the desktop thread composer, no manual @mention — the owner replying to an agent inside that agent's own thread:

    [["h","3bcb324f-…"],["e","3472cd23…","","root"],["e","f20056c6…","","reply"]]
    

    Agent reply from buzz-acp (kind 9 answer to a mention):

    [["h","3bcb324f-…"],["e","3472cd23…","","reply"]]
    

    Neither carries a p. Because buzz-acp gates on require_mention (a p tag containing its own pubkey), the human reply above was never delivered to the agent it was addressed to — the "looks like the agent ignored me" experience described above, reproduced exactly.

    One consequence worth weighing before this lands: the missing p tag on agent replies is currently the only thing preventing agent↔agent reply chains. In a channel where several agents run --respond-to=allowlist carrying each other's pubkeys, an agent's reply structurally cannot wake a peer today. Once replies carry the parent author's p tag, every agent reply to another agent becomes a wake-up, and nothing bounds the exchange — --max-turns-per-session rotates the session rather than ending it. Suggest shipping this together with (or at minimum documenting) a bounded agent↔agent turn policy; otherwise the fix converts a notification bug into a runaway-loop hazard for multi-agent deployments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions