buzz-acp: thread-reply @mention to an idle agent is swallowed by the steer path (ExpectedRunIdMissing, no turn in flight)
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Summary
A single `@mention` of a managed `buzz-acp` agent **in a thread reply** is silently swallowed when the agent is **completely idle** — no turn in flight, nothing queued, nothing running.
The mention is received and routed down the `steer` path (`meh=steer`, the default). Steer then looks for the run it is supposed to steer, finds none, fails with `ExpectedRunIdMissing`, and the event is consumed as a control signal. No turn is ever started, no reply is posted, and nothing is surfaced in the UI — the mention just disappears.
A new top-level message in the same channel works every time. Only thread replies are affected.
This is closely related to #3071 and #3176, but the trigger here is materially different and I think narrows the root cause — see *Why this isn't a duplicate* below.
## Environment
- Buzz Desktop `0.4.26` (AppImage), Ubuntu 24.04.3 LTS, x86_64
- Agent runtime: `@agentclientprotocol/claude-agent-acp` `0.63.0`, Node `v24.11.0`
- Relay: self-hosted community relay (address omitted from this public report)
- Agent config, verbatim from the harness startup line:
```text
subscribe=Mentions dedup=Queue meh=Steer ignore_self=true context_limit=12
max_turns_per_session=0 presence=true typing=true memory=true
model=(agent default) permission_mode=bypassPermissions respond_to=owner-only
```
Pubkeys, channel IDs, event IDs and the relay address are redacted below.
## Reproduction
1. Start a managed `buzz-acp` agent with default `meh=steer` and let it settle to idle.
2. Confirm it is genuinely idle — no turns for several minutes.
3. In a channel it is subscribed to, `@mention` the agent **as a reply inside an existing thread**.
4. Observe: no response, no typing indicator, no error in the UI.
5. `@mention` the same agent in a **new top-level message** — it responds normally.
## Evidence
Harness log, `~/.local/share/xyz.block.buzz.app/agents/logs/__<...>.log`.
Note the timestamps. The agent came online at `08:18:36` and logged **nothing at all** for the next five minutes. There was no possible in-flight turn:
```text
08:18:33.775 INFO buzz_acp: agent_pool_ready agents=24
08:18:34.914 INFO buzz_acp: connected to relay at
08:18:36.030 INFO buzz_acp: subscribed to channel
08:18:36.030 INFO buzz_acp: subscribed to channel
08:18:36.031 INFO buzz_acp: presence set to online
── 5m 08s with no log output whatsoever; agent idle ──
08:23:44.715 WARN buzz_acp::acp: goose-native steer: no active_run_id at write time
(no session/update seen yet) — falling back to cancel+merge
08:23:44.715 INFO buzz_acp: non-cancelling steer ack received channel=
event_id= ack=Ok(Err(ExpectedRunIdMissing))
release_withheld=true drop_withheld=false signal_fallback=true
08:23:44.716 INFO buzz_acp: control signal sent to in-flight task channel=
mode=Steer
```
`control signal sent to in-flight task` is emitted for an agent that has been idle for over five minutes. After this, the log is silent — no session start, no prompt dispatch, no reply.
This is reproducible and not a one-off. Same signature, same channel, three separate occasions across two days:
```text
2026-07-27 19:42:23 ack=Ok(Err(ExpectedRunIdMissing))
2026-07-27 23:00:45 ack=Ok(Err(ExpectedRunIdMissing))
2026-07-28 08:23:44 ack=Ok(Err(ExpectedRunIdMissing))
```
## Why this isn't a duplicate
- **#3071** (voice huddles) has an identical log signature, but its stated mechanism is rapid, short utterances arriving faster than a run ID can be exposed — a race against an *actively starting* turn. It is framed as voice-specific.
- **#3176** notes steer failing on a six-event fixture sent one second apart — again, concurrent events racing a run.
- **#3105** is about mentions that never reach the steer path at all. Here the mention *does* reach it.
In this report there is **no concurrency at all**: one mention, one idle agent, five minutes of quiet either side. That suggests the precondition for entering the steer path is wrong independently of any race — the harness treats a thread-reply mention as "mid-turn" when there is demonstrably no turn. If so, #3071's voice symptom may be one visible consequence of a more general defect rather than the defect itself.
## Expected behavior
A mention that arrives when no turn is in flight should start a new turn, whether it is a top-level message or a thread reply.
If the steer path is entered and returns `ExpectedRunIdMissing`, the event should fall back to normal dispatch rather than being consumed. Silently dropping user input is the worst possible outcome — nothing is shown in the UI, so the message simply vanishes with no indication anything went wrong.
## Workaround, and its cost
Setting `BUZZ_ACP_MULTIPLE_EVENT_HANDLING=queue` avoids the steer path and restores thread mentions. But per #3176 queue mode batches pending events into a single turn, so this trades silent message loss for loss of per-event reply identity. Both defaults are lossy in different ways; there is currently no mode that is simply correct for a single thread mention to an idle agent.
Contributor guide
Research direction
Reproduce with a managed buzz-acp agent using meh=Steer, an idle session, and a thread-reply mention, then compare the harness log with a top-level mention. Start from the buzz_acp::acp log entries showing ExpectedRunIdMissing and the control-signal path; compare behavior with BUZZ_ACP_MULTIPLE_EVENT_HANDLING=queue and the related issues #3071, #3176, and #3105. Done means an idle thread mention starts a turn or falls back to normal dispatch instead of being consumed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- ai-infra-agents, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100