buzz-acp advertises `protocolVersion: 2` but implements v1 semantics — every v2-capable ACP adapter fails (initialize -32602, then missing stopReason)
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 68/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- javascript, rust
Research direction
Start in crates/buzz-acp/src/acp.rs, especially build_initialize_params() around line 126 and the initialize error path around agent_error_from_json(). Run the supplied agy-acp@0.4.3 initialize repro, then verify a v1-compatible handshake and first prompt work without the protocol mismatch or an opaque initialization error.
Written by the indexing model from the issue text.
Description
Summary
buzz-acp hardcodes "protocolVersion": 2 in its initialize request but implements ACP v1 semantics throughout. Any adapter that actually supports v2 therefore negotiates v2, behaves correctly for v2, and breaks Buzz — twice, at two different layers.
This blocks the path recommended in #2393, where the generic answer to "please support runtime X" is that any ACP-over-stdio binary can be registered from Settings. That is true only for v1-only adapters. A v2-capable adapter cannot be registered today.
Found while wiring Google Antigravity CLI (agy) via the third-party adapter agy-acp as a Custom harness, which is precisely the flow #2393 was closed in favour of.
Symptom 1: initialize fails with -32602
INFO buzz_acp: buzz-acp starting: agent_cmd=/Users/ash/.local/bin/agy-acp ... agents=10
ERROR buzz_acp: agent initialize failed: Agent reported error (code -32602): Invalid params agent=0
... identical for agents 1-9 ...
Error: all 10 agents failed to start — cannot continue
build_initialize_params() (crates/buzz-acp/src/acp.rs:126) sends protocolVersion: 2 with a v1-shaped body: clientCapabilities and clientInfo, and no info. Draft ACP v2 renames clientInfo to info and makes it required, so a v2 router validates against the v2 schema and rejects the handshake.
Repro
npm i -g agy-acp@0.4.3
printf '%s\n' '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":2,"clientCapabilities":{"auth":{"terminal":true},"_meta":{"goose":{"customNotifications":true},"terminal-auth":true}},"clientInfo":{"name":"buzz-acp","version":"0.1.0"}}}' | agy-acp
Actual:
{"jsonrpc":"2.0","id":0,"error":{"code":-32602,"message":"Invalid params","data":"invalid initialize params: [{\"expected\":\"object\",\"code\":\"invalid_type\",\"path\":[\"info\"],\"message\":\"Invalid input: expected object, received undefined\"}]"}}
Isolated across 15 payload variants: clientCapabilities, _meta, auth and the presence of clientInfo are all irrelevant, and the schema tolerates unknown keys. It is strict only about info. Rejecting schema is @agentclientprotocol/sdk@1.3.0, dist/v2/schema/zod.gen.js:2488 (info: zImplementation, no .optional()), thrown from dist/protocol-router.js:399.
Symptom 2: adding info moves the failure one layer down
Injecting params.info makes the handshake succeed with result.protocolVersion == 2. The pool starts, the agent joins the channel and reports commands available. The first prompt then fails:
Turn error · error: Protocol error: session/prompt response missing stopReason
This is not a second bug. It is the same one surfacing where it actually matters. From agy-acp's own source (dist/acp/agent.js:261-268):
v1 prompt lifecycle: response carries
stopReasonafter the full turn.
v2: progress andstopReasonarrive asstate_updatenotifications.
Under v2 the prompt response has no stopReason by design. buzz-acp waits for it in the response, which is v1 behaviour. So Buzz asks for v2, gets v2, and cannot consume it.
Why it works with the bundled adapters
claude-agent-acp is v1-only. It parses {"protocolVersion": 2} fine, clamps its reply to "protocolVersion": 1, and buzz-acp accepts the downgrade. The tolerant v1 schema is the only one that ever runs, so the mismatch stays invisible. Same for codex-acp. It surfaces the moment an adapter is capable of honouring the version Buzz asked for.
Impact
Every pool slot fails identically before any prompt, so the run aborts. No v2-capable ACP adapter can be used with Buzz today, and the failure is opaque: -32602 Invalid params with no indication that a protocol version is involved.
Suggested fix
Either:
- Send
info: {name, version}alongsideclientInfoin the initialize params (v1 agents ignore unknown keys, so one body serves both) and implement the v2 prompt lifecycle, consumingstopReasonfromstate_updatenotifications; or - Revert the pin at
acp.rs:126to"protocolVersion": 1until the v2 body and lifecycle are implemented.
(2) is the smaller change and restores correctness immediately. The comment at that line notes Buzz is squatting on ACP v2 ahead of the upstream RFD; the problem is that adapters take the advertised version at face value.
Secondary: the error is undiagnosable from the logs
agent_error_from_json (crates/buzz-acp/src/acp.rs:115) surfaces only error.message. The v2 SDK puts the zod detail in error.data and leaves message as the bare string "Invalid params", so operators see a detail-free error ten times over. Logging error.data on initialize failure would have made this self-diagnosing in seconds. Related: #4069 notes the same error.data loss for a different error, and #3338 covers the misleading "all N agents failed to start" wording.
Workaround
A stdio shim that clamps the initialize request to v1 before forwarding, leaving everything else verbatim. Verified working end to end with agy-acp@0.4.3:
#!/usr/bin/env node
const { spawn } = require("node:child_process");
const target = process.env.AGY_ACP_BIN; // real adapter entry
const child = spawn(process.execPath, [target, ...process.argv.slice(2)],
{ stdio: ["pipe", "pipe", "inherit"], env: process.env });
child.stdout.pipe(process.stdout);
child.on("exit", (c, s) => process.exit(s ? 1 : (c ?? 0)));
let patched = false, buf = "";
const clamp = (line) => {
if (patched || !line.includes('"initialize"')) return line;
let m; try { m = JSON.parse(line); } catch { return line; }
if (m.method !== "initialize" || !m.params) return line;
patched = true;
if (typeof m.params.protocolVersion === "number" && m.params.protocolVersion > 1) {
m.params.protocolVersion = 1;
return JSON.stringify(m);
}
return line;
};
process.stdin.on("data", (c) => {
buf += c.toString("utf8");
let i;
while ((i = buf.indexOf("\n")) !== -1) {
const line = buf.slice(0, i); buf = buf.slice(i + 1);
child.stdin.write((line.trim() ? clamp(line) : line) + "\n");
}
});
process.stdin.on("end", () => { if (buf.length) child.stdin.write(buf); child.stdin.end(); });
Register that as the Custom harness Command instead of the adapter itself.
Versions
- Buzz Desktop v0.5.4, buzz-acp 0.1.0
agy-acp0.4.3,@agentclientprotocol/sdk1.3.0- Google Antigravity CLI (
agy), macOS 15 (Darwin 25.5.0), node 22.23.1 - Relay: managed
*.communities.buzz.xyz
- Dominant language
- Rust
- Stars
- 33.7k
- Forks
- 4.4k
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 239
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from block/buzz
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
workflow_sink's mention parser never masks code regions — @name inside a code span wakes the agent Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 Half a day Newbie friendliness 88/100
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
gitbutlerapp/gitbutler#15998 · 1 comment ·
-
bug triage:deciding
Difficulty 1/5 Under an hour Newbie friendliness 88/100
open-telemetry/otel-arrow#4132 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
bitcoindevkit/bdk-ffi#1125 ·