DM: agent never posts a reply to a top-level DM — the turn context omits the send instruction when there is no thread root
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 84/100
Research direction
Start in crates/buzz-acp/src/queue.rs and compare the Scope: dm branch with the channel branch, focusing on append_reply_instruction and append_new_thread_reply_instruction. Verify that a top-level DM context includes a send instruction anchored to the triggering event, and that the agent posts a reply without requiring a thread root.
Written by the indexing model from the issue text.
Description
Summary
When a user sends the first, top-level message in a DM to an agent, the agent runs the turn, does the
work, composes an answer — and never posts it. From the user's side the agent simply never replies.
The cause is in the prompt the harness builds: the DM branch attaches the "reply with buzz messages send"
instruction only when the triggering event is already inside a thread. A top-level DM has no thread root,
so the agent receives a context block that tells it how to read the conversation but never how to send
anything. The channel branch does not have this gap — it covers both the threaded and the top-level case.
Reproduction
- Open a DM with an agent.
- Send a message that is not a reply to anything (a fresh top-level message).
- The agent picks up the turn and works, but nothing is posted back.
- Now reply to your own message (or to any message in that DM) and ask again — the agent answers normally.
Evidence
Two consecutive turns in the same DM session. Only the second one contains the send instruction, and only the
second one results in a published event:
| turn | triggering message | thread root | context block | buzz messages send calls |
reply posted |
|---|---|---|---|---|---|
| 1 | top-level DM | absent | 742 chars, no send instruction | 0 | no |
| 2 | reply (carries an e tag to turn 1) |
present | 1466 chars, send instruction present | 2 | yes |
Turn 1 was not a failed send. The agent completed the turn cleanly — it listed channels, read the day's
messages with buzz messages get, and produced a full answer as its final assistant text. It simply never
called the send command, and the relay log shows no kind:9 event published by the agent in that window.
The same agent posted replies normally in channels throughout the same period (4-15 send calls per turn).
For contrast, channel-scope turns in the same session period carry the instruction in both shapes:
Scope: channel
Channel: ...
Hint: Use `buzz messages get --channel <UUID>` for recent messages if needed.
IMPORTANT: This is a new top-level message. For ordinary replies in this turn, use
`--reply-to <event-id>` on `buzz messages send` ...
while the failing DM turn carried only:
Scope: dm
Channel: DM (#<uuid>)
<context hint>
Root cause
crates/buzz-acp/src/queue.rs, DM branch (Scope: dm):
// If this is a DM reply, include thread structural info as supplementary.
if let Some(ref root) = thread_tags.root_event_id {
s.push_str(&format!("\nThread root: {root}"));
...
if let Some(event_id) = reply_anchor {
append_reply_instruction(&mut s, event_id); // <- only reached inside a thread
}
}
The channel branch immediately below handles the same two cases symmetrically:
// thread case
if let Some(event_id) = reply_anchor {
append_reply_instruction(&mut s, event_id);
}
// top-level case
if let Some(event_id) = reply_anchor {
append_new_thread_reply_instruction(&mut s, event_id);
}
append_reply_instruction and append_new_thread_reply_instruction are the only places that mention
buzz messages send in the turn context, so when neither fires the agent has no instruction to publish
anything.
Related: resolve_reply_anchor is documented as "Resolve the --reply-to anchor for a non-DM turn",
which suggests the DM path was intended to be handled separately and the top-level sub-case was missed.
Suggested fix
Give the DM branch the same top-level handling the channel branch has — attach
append_new_thread_reply_instruction (anchored to the triggering event) when thread_tags.root_event_id is
None. That keeps DM replies threaded on the triggering message, matching channel behaviour.
A cheaper alternative, if threading in DMs is deliberately looser, is to always state that replies are sent
with buzz messages send in the DM context block and leave the --reply-to anchor optional.
Impact
The first message a user ever sends an agent in a DM is by definition top-level, so this is the most likely
DM interaction to hit. The agent looks unresponsive with no error anywhere: no failed command, no rejected
event, nothing in the relay log — the work is done and the answer is discarded. Users have no way to tell
this apart from the agent being broken.
- Dominant language
- Rust
- Stars
- 33.7k
- Forks
- 4.4k
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 239
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from block/buzz
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
workflow_sink's mention parser never masks code regions — @name inside a code span wakes the agent Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 Half a day Newbie friendliness 88/100
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
gitbutlerapp/gitbutler#15998 · 1 comment ·
-
bug triage:deciding
Difficulty 1/5 Under an hour Newbie friendliness 88/100
open-telemetry/otel-arrow#4132 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
bitcoindevkit/bdk-ffi#1125 ·