block / block/buzz

buzz-acp: turns silently produce no channel message when the model answers in text without calling `buzz messages send`

Open
#6,160 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.