buzz-acp: turns silently produce no channel message when the model answers in text without calling `buzz messages send`
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Summary
A turn can complete fully green — `turn complete ... end_turn`, `agent_returned outcome="ok"` — while nothing is published to the channel, because replying depends on the model choosing to run `buzz messages send` itself. To the user this is indistinguishable from a hang: no message, no error, no warning anywhere.
## Reproduce
1. Run `buzz-acp` with `--agent-command claude-code-acp` (adapter 0.16.2).
2. Configure a terser model (`model: sonnet` in `~/.claude/settings.json`).
3. Mention the agent with a prompt that invites a one-word answer.
Observed (relay-side): no message in channel. Harness log:
```
INFO acp::stream: ok
INFO pool::prompt: turn complete for channel : end_turn
DEBUG buzz_acp: agent_returned agent=0 outcome="ok"
```
Claude Code transcripts make the difference explicit:
| model | tool call | channel |
|---|---|---|
| claude-sonnet-4-5 | none — plain text `ok` | nothing posted |
| claude-opus-4-6 | `buzz messages send --channel ...` | message posted |
So the base prompt contract works with a strong model and fails silently with a terser one.
## Why this matters
The failure mode is invisible: every signal the operator can see says success. Diagnosing it requires reading the agent runtime transcript, which is outside Buzz.
## Suggested fix
A harness-side safety net in `buzz-acp`: the client already sees `agent_message_chunk` and `tool_call` updates, so it can track, per turn, the streamed assistant text and whether any tool call happened. On `end_turn` for a `PromptSource::Channel`, if the agent produced text but published nothing, publish that text as the reply (or at minimum log a warning instead of `outcome="ok"`). Making it opt-out via a flag keeps current behaviour available.
Happy to send a PR if the approach sounds right.
## Workaround
Stating the contract explicitly in the system prompt ("every reply, even one word, must be sent with `buzz messages send`") made sonnet comply — verified by a tool call in the transcript and the message landing in the channel.
## Environment
self-hosted relay (compose bundle, `ghcr.io/block/buzz@sha256:7256c46`), `buzz-acp` built from main, Ubuntu 24.04 arm64, `@zed-industries/claude-code-acp` 0.16.2
Contributor guide
Research direction
Start in buzz-acp's turn handling and trace the agent_message_chunk and tool_call updates through end_turn for PromptSource::Channel. Verify how published messages are detected, then define and test the chosen fallback or warning behavior, including its opt-out setting, for plain-text replies with no tool call.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- ai, cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100