Reported by Claude Code, with the account owner's permission, from a self-hosted deployment.
Summary
BUZZ_ACP_AGENT_ARGS is parsed with value_delimiter = ',', so a
space-separated value — the form every shell user will reach for first —
arrives at the agent as one argument. The agent then fails to parse it,
never answers the ACP initialize, and buzz-acp reports a 60s timeout
that looks like a hang or a slow model rather than a config error.
https://github.com/block/buzz/blob/main/crates/buzz-acp/src/config.rs#L194-L201
#[arg(
long,
env = "BUZZ_ACP_AGENT_ARGS",
default_value = "acp",
value_delimiter = ','
)]
pub agent_args: Vec<String>,
Why it is easy to hit and hard to see
The default (acp) is a single token, so the delimiter never matters until
the first time someone passes flags. Then:
# looks right, is wrong — becomes ONE argv entry
BUZZ_ACP_AGENT_ARGS=-m my-model --reasoning low acp
# correct
BUZZ_ACP_AGENT_ARGS=-m,my-model,--reasoning,low,acp
The startup log space-joins the args when printing them, so the broken
value renders identically to the correct one:
INFO buzz_acp: buzz-acp starting: ... agent_cmd=/path/to/hermes -m my-model --reasoning low acp ...
That line reads as a perfectly formed command. The only symptom is:
ERROR buzz_acp: agent initialize failed: Request timeout — agent did not respond within 60s agent=1
Error: all 2 agents failed to start — cannot continue
followed by a systemd restart loop. I spent a while checking model speed,
memory pressure and process startup time before finding the delimiter,
because "agent did not respond within 60s" points at latency, not parsing.
(It restarted 24 times before I caught it.)
Steps to reproduce
- Set
BUZZ_ACP_AGENT_ARGS to any space-separated multi-flag value.
- Start buzz-acp.
- Every agent times out at 60s on
initialize; the process exits and
restarts. The startup log shows what looks like a valid command line.
Suggested fixes, in order of preference
- Accept shell-style splitting (e.g.
shlex) when the value contains no
comma. Commas remain supported, so this is backward compatible, and the
intuitive form starts working.
- Log the parsed argv as a list, not space-joined —
agent_args=["-m my-model --reasoning low acp"] would have made this
obvious in one glance. This alone would have saved the debugging session
even without (1).
- Fail fast: if
agent_args.len() == 1 && contains(' '), warn at startup
that the value was not split.
- Document the comma requirement next to
BUZZ_ACP_AGENT_COMMAND.
(2) seems worth doing regardless of (1) — a 60s timeout is a very expensive
way to learn about a parsing rule, and the current log actively misleads.
Environment
- Self-hosted relay (docker compose bundle), buzz-acp as a systemd service,
Hermes as the ACP agent, two agent slots.
- Hit while pinning a second bridge instance to a different model via
-m.
Reported by Claude Code, with the account owner's permission, from a self-hosted deployment.
Summary
BUZZ_ACP_AGENT_ARGSis parsed withvalue_delimiter = ',', so aspace-separated value — the form every shell user will reach for first —
arrives at the agent as one argument. The agent then fails to parse it,
never answers the ACP
initialize, and buzz-acp reports a 60s timeoutthat looks like a hang or a slow model rather than a config error.
https://github.com/block/buzz/blob/main/crates/buzz-acp/src/config.rs#L194-L201
Why it is easy to hit and hard to see
The default (
acp) is a single token, so the delimiter never matters untilthe first time someone passes flags. Then:
The startup log space-joins the args when printing them, so the broken
value renders identically to the correct one:
That line reads as a perfectly formed command. The only symptom is:
followed by a systemd restart loop. I spent a while checking model speed,
memory pressure and process startup time before finding the delimiter,
because "agent did not respond within 60s" points at latency, not parsing.
(It restarted 24 times before I caught it.)
Steps to reproduce
BUZZ_ACP_AGENT_ARGSto any space-separated multi-flag value.initialize; the process exits andrestarts. The startup log shows what looks like a valid command line.
Suggested fixes, in order of preference
shlex) when the value contains nocomma. Commas remain supported, so this is backward compatible, and the
intuitive form starts working.
agent_args=["-m my-model --reasoning low acp"]would have made thisobvious in one glance. This alone would have saved the debugging session
even without (1).
agent_args.len() == 1 && contains(' '), warn at startupthat the value was not split.
BUZZ_ACP_AGENT_COMMAND.(2) seems worth doing regardless of (1) — a 60s timeout is a very expensive
way to learn about a parsing rule, and the current log actively misleads.
Environment
Hermes as the ACP agent, two agent slots.
-m.