Summary
thread_replies from a persona pack has no effect. An agent configured with
thread_replies: false still opens a new thread for every top-level channel message,
because append_new_thread_reply_instruction() unconditionally appends an IMPORTANT:
directive telling the model to use --reply-to <event_id>.
This is the same class of gap as #2899 (mcp_servers parsed and validated but never
plumbed to the runtime).
Why this should work
PERSONA_PACK_SPEC.md §10 states the behavioral config fields are the harness's job:
The behavioral config fields in a persona's frontmatter control how the agent
participates in Buzz conversations. These are all Buzz-specific — the agent runtime
has no awareness of them.
And thread_replies is documented as:
| thread_replies | bool | true | true / false | Reply in-thread when the
triggering message is in a thread. |
Since the agent runtime is explicitly not aware of these fields, buzz-acp is the only
component that can honour them.
Actual behaviour
thread_replies does not appear anywhere in crates/buzz-acp. It exists only in
crates/buzz-persona (parse, merge, resolve, manifest) and crates/buzz-db. It is
parsed, merged and validated — buzz pack inspect even prints Thread replies: false —
and then dropped.
The prompt builder in crates/buzz-acp/src/queue.rs takes the else branch for a
top-level channel message and always calls:
fn append_new_thread_reply_instruction(s: &mut String, event_id: &str) {
s.push_str(&format!(
"\nIMPORTANT: This is a new top-level message. For ordinary replies in \
this turn, use `--reply-to {event_id}` on `buzz messages send` — the \
triggering message is the thread root. Do NOT reply into any other \
(older) thread. ..."
));
}
There is no configuration path that suppresses this.
Why prompting cannot fix it
We tried. Both the persona system prompt and a patched base prompt instruct the agent to
reply flat in the channel and to ignore any reply target suggested in [Context]. The
model still threads, and inconsistently so — flat at 13:03, threaded at 14:28 on the same
kind of question.
The reason is prompt position and specificity. The harness directive is marked
IMPORTANT:, carries the concrete event ID, and sits at the very end of the prompt; the
persona rule is abstract and much earlier. The concrete, closer instruction wins. Verified
in the agent's own request logs — the model received the directive and complied exactly:
buzz messages send --channel 29c37e15-… --reply-to cb710fe8… --content -
Reproduce
- Persona pack with
thread_replies: false; confirm with buzz pack inspect.
- Run
buzz-acp (any agent command) subscribed to a channel.
- Post a new top-level message in that channel — not inside a thread.
- The reply is threaded under the triggering message.
Observed on 3d7712cc36e8da563cb1c121fc58bfc505d38496, still present on main at time of
writing.
Suggested fix
Gate the call site on the resolved thread_replies value. The split is already in the
right place — append_reply_instruction() (replying inside an existing thread) is
correct as-is and should keep working; only the new-thread branch needs to respect the
flag.
Note that the unit tests in queue.rs assert on the current wording
("new top-level message", --reply-to <id>), so they would need a thread_replies: false counterpart.
Workaround
Patching append_new_thread_reply_instruction() at build time to emit the opposite
instruction. Works, but it means carrying a source patch against a pinned upstream commit.
Summary
thread_repliesfrom a persona pack has no effect. An agent configured withthread_replies: falsestill opens a new thread for every top-level channel message,because
append_new_thread_reply_instruction()unconditionally appends anIMPORTANT:directive telling the model to use
--reply-to <event_id>.This is the same class of gap as #2899 (
mcp_serversparsed and validated but neverplumbed to the runtime).
Why this should work
PERSONA_PACK_SPEC.md§10 states the behavioral config fields are the harness's job:And
thread_repliesis documented as:Since the agent runtime is explicitly not aware of these fields,
buzz-acpis the onlycomponent that can honour them.
Actual behaviour
thread_repliesdoes not appear anywhere incrates/buzz-acp. It exists only incrates/buzz-persona(parse, merge, resolve, manifest) andcrates/buzz-db. It isparsed, merged and validated —
buzz pack inspecteven printsThread replies: false—and then dropped.
The prompt builder in
crates/buzz-acp/src/queue.rstakes theelsebranch for atop-level channel message and always calls:
There is no configuration path that suppresses this.
Why prompting cannot fix it
We tried. Both the persona system prompt and a patched base prompt instruct the agent to
reply flat in the channel and to ignore any reply target suggested in
[Context]. Themodel still threads, and inconsistently so — flat at 13:03, threaded at 14:28 on the same
kind of question.
The reason is prompt position and specificity. The harness directive is marked
IMPORTANT:, carries the concrete event ID, and sits at the very end of the prompt; thepersona rule is abstract and much earlier. The concrete, closer instruction wins. Verified
in the agent's own request logs — the model received the directive and complied exactly:
Reproduce
thread_replies: false; confirm withbuzz pack inspect.buzz-acp(any agent command) subscribed to a channel.Observed on
3d7712cc36e8da563cb1c121fc58bfc505d38496, still present onmainat time ofwriting.
Suggested fix
Gate the call site on the resolved
thread_repliesvalue. The split is already in theright place —
append_reply_instruction()(replying inside an existing thread) iscorrect as-is and should keep working; only the new-thread branch needs to respect the
flag.
Note that the unit tests in
queue.rsassert on the current wording(
"new top-level message",--reply-to <id>), so they would need athread_replies: falsecounterpart.Workaround
Patching
append_new_thread_reply_instruction()at build time to emit the oppositeinstruction. Works, but it means carrying a source patch against a pinned upstream commit.