buzz-acp 0.5.22: [Base] and --system-prompt-file never reach claude-agent-acp (protocol v1) — every reply is then silently dropped
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Summary
Since upgrading `buzz-acp` to the binary shipped in Buzz Desktop **0.5.22**, neither the compiled-in `[Base]` platform prompt nor the agent's own `--system-prompt-file` persona reaches a `claude-agent-acp` session. The agents run as bare Claude Code sessions that receive only the per-turn `` / `` / `` blocks.
The visible consequence is worse than a missing prompt: `[Base]` is the only place that states the delivery contract —
> **If your turn produced anything worth knowing, you MUST publish it.** Use `buzz messages send`. Your reasoning and tool calls are invisible…
Without it the model answers in plain session text, the harness does not publish it (by design, see #2698), and the turn ends `agent_returned outcome="ok"` with nothing in the channel. **Seven consecutive replies were lost this way before we noticed**, across two machines and two agents.
This is the same failure class as #2698 / #5390 / #3980, but with a concrete new trigger: the prompt that used to prevent it stopped being delivered.
## Impact
Silent. The unit is healthy, the turn is claimed, tool calls run, `👀`/`💬` reactions are published and then retracted with `kind:5`, and `outcome="ok"` is logged. Nothing distinguishes it from an agent that legitimately had nothing to say. It reads as bad agent behaviour, and we spent hours diagnosing it as such — one of our agents even reprimanded the other for "ending a turn without a message" while doing exactly the same thing for the same reason.
## Environment
- `buzz-acp` extracted from the **Buzz Desktop 0.5.22** AppImage (previous binary: a build from 2026-08-04)
- `@agentclientprotocol/claude-agent-acp` **0.70.0**, Claude Code 2.1.261, node from nix
- self-hosted relay (Postgres 17 + Redis 7 + MinIO), reached over `wss://`
- systemd user units, `Type=simple`, config via `EnvironmentFile`
- relevant env: `BUZZ_ACP_SYSTEM_PROMPT_FILE` set, `BUZZ_ACP_SESSION_POLICY=thread`, `BUZZ_ACP_AGENTS=1`, `BUZZ_ACP_MODEL=opus[1m]`, `BUZZ_ACP_PERMISSION_MODE` left at default
- **`BUZZ_ACP_NO_BASE_PROMPT` is not set** and `--base-prompt-file` is not used
## Evidence
**1. The prompt is in the session on the old binary and absent on 0.5.22.** Counting the string `operating inside the Buzz platform` in the Claude Code session transcripts (`~/.claude/projects//*.jsonl`):
| Session | Binary | Scope | Occurrences |
|---|---|---|---|
| agent A, last session before upgrade | 2026-08-04 | dm / conversation | **13** |
| agent A, first session after upgrade | 0.5.22 | dm / conversation | **0** |
| agent B, channel turn | 0.5.22 | thread | **0** |
| agent B, DM turn | 0.5.22 | dm / conversation | **0** |
The persona from `--system-prompt-file` is missing in exactly the same sessions (0 occurrences of a distinctive line from that file). On the old binary the first user message of the session begins:
```text
[Base]
You are operating inside the Buzz platform — a Nostr-based messaging platform for human-agent collaboration.
...
[System]
[Agent Memory — core]
...
```
On 0.5.22 the first user message begins directly with ``.
**2. It is not a stripped prompt in the build.** `strings` on the 0.5.22 binary still contains the base prompt, including the delivery-contract line, at the expected place. So the text exists and is simply not delivered.
**3. The adapter negotiates protocol v1**, which per #3126 is the branch where the `session/new` system prompt is discarded and the legacy in-band path is supposed to take over:
```text
INFO buzz_acp: agent initialized: {... "agentInfo":{"name":"@agentclientprotocol/claude-agent-acp","version":"0.70.0"}, ... "protocolVersion":1}
INFO buzz_acp: agent initialized agent=0 name="@agentclientprotocol/claude-agent-acp" steering_supported=true
```
**4. Relay side.** Across seven turns on 0.5.22 the agents published only `kind:7` (`👀`, `💬`), then two `kind:5` retractions per turn, and zero `kind:9`. In every one of those turns the final assistant text is present in the session transcript, so generation succeeded and only delivery never happened.
**5. Behaviour matches.** On the old binary the agent published every reply itself: **20 of 20** `buzz messages send` calls. On 0.5.22, across the same kind of turns, **0**. It also stopped passing `--reply-to`, which the `[Base]` threading section governs — consistent with the whole section being absent rather than the model choosing differently.
## Regression window
- prompt re-framing landed 2026-08-26: #6701 (paired tags), #6706 (dedup)
- per-thread agent sessions landed 2026-08-31: #6732
- `[Base]` was still delivered by a build from 2026-08-04; it is not delivered by 0.5.22 (tagged 2026-09-04)
Worth noting for anyone hitting this: because the re-framing is *older* than the thread-scoped sessions, there is no released version that has `--session-policy=thread` and a working `[Base]`. 0.5.22 is currently the newest release.
## Suspected cause (hypothesis — I have not read the 0.5.22 source)
Per #3126, for a protocol-v1 agent the combined `session/new` system prompt is built and then discarded, and `prepend_base_for_legacy` is the path that renders `[Base]` in-band. Something in the re-framing / session-scoping work appears to have left that path unreached for sessions created by the newer scoping code — both `Conversation(dm)` and `Thread(channel, root)` sessions come up without it.
## Steps to reproduce
1. Run `buzz-acp` from 0.5.22 with `--agent-command claude-agent-acp` and `--system-prompt-file `.
2. `@mention` the agent (channel or DM).
3. Open the resulting Claude Code session transcript and search for `operating inside the Buzz platform` and for any line unique to the persona file — both are absent.
4. Ask the agent something that needs an answer. It answers in session text, publishes nothing, and the turn ends `outcome="ok"`.
## Expected
`[Base]` and the `--system-prompt-file` persona reach the session on protocol-v1 adapters, as they did before, or the harness fails loudly when it cannot deliver them.
## Workaround, for anyone else hitting this
Give each agent its own working directory and put the instructions there as `CLAUDE.md`, which Claude Code loads from the cwd independently of the harness:
```text
~/.agents//CLAUDE.md # persona (same file passed to --system-prompt-file)
~/.agents//.claude/CLAUDE.md # the delivery contract lifted from [Base]
```
Two caveats we measured, since both fail silently:
- A **symlinked** `CLAUDE.md` (or `.claude/CLAUDE.md`) pointing outside the working directory **is** loaded. An `@import` or a `.claude/rules/` entry resolving outside the working directory **is not** — it is treated as an external import awaiting an approval dialog that never appears in a headless run.
- `CLAUDE.md` content does **not** appear in the session transcript, unlike the in-band `[Base]`, so grepping the transcript is not a valid check that the workaround is live. Probe it with `cd && claude -p '...'` instead.
A per-agent directory is required rather than one shared file: `CLAUDE.md` is also inherited from every parent directory, so two agents sharing a working directory cannot have different personas, and anything placed in `$HOME` leaks into all of them.
## Related
#2698 (implicit delivery contract), #5390, #3980, #4709, #5446 (same failure class), #3126 and #3124 (protocol-v1 system-prompt path), #6701, #6706, #6732 (the changes in the regression window).
Contributor guide
Research direction
Start at the buzz-acp entry point handling protocol-v1 sessions, especially the --system-prompt-file path and prepend_base_for_legacy around session creation. Compare the behavior and recent changes in #3126, #6701, #6706, and #6732, then reproduce with claude-agent-acp and inspect the session transcript. Done means both prompts reach the session and a normal reply is published rather than silently dropped.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend, cli, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100