block / block/buzz

Provider protocol: `launch.command` is the inner ACP agent, not the process to exec — a conformant provider can ship silently inert agents

Open
#5,548 1 comment 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

Writing a third-party `buzz-backend-*` provider, I shipped a deploy that Buzz
reported as fully successful — `backend_agent_id` returned, `last_error: null`,
worktree created, process alive — and which produced a **completely inert
agent**. Nothing was connected to the relay.

The cause: I exec'd `launch.command` as the process to run. It is actually the
ACP agent that runs *under* `buzz-acp`; the harness is what authenticates to the
relay, listens for mentions, and drives the agent over stdio. A provider is
responsible for running the harness and passing the inner agent through
`BUZZ_ACP_AGENT_COMMAND` / `BUZZ_ACP_AGENT_ARGS`.

That is a reasonable contract. The problem is that nothing states it, and
nothing can catch getting it wrong.

## Why the docs didn't prevent it

`docs/remote-agents.md` §Launch data describes the field as:

```
"launch": {
"command": str, // command NAME (e.g. "goose"), never a host path
"args": [str], // normalized args, definition fallback applied
```

Read on its own, `command` + `args` reads unambiguously as *the thing to
execute*. The spec does say elsewhere that `agent_command`/`agent_args` are
"the ACP agent under the harness", but the `deploy` contract never states that
the provider must supply the harness, and §Launch data — the section a provider
author works from — doesn't mention `buzz-acp` at all.

## Why no test catches it

Every `deploy-*.request.json` fixture in
`crates/buzz-backend-kubernetes/tests/fixtures/provider-wire/` carries **no
launch command at all** — `deploy-no-owner`, `deploy-relay-mesh`,
`deploy-relay-mesh-padded`, `deploy-tag-image` have neither `launch` nor
`agent_command`. That is correct for the Kubernetes binding, whose container
image `ENTRYPOINT` is the harness (§K8s Entrypoint). `deploy-full-launch` does
carry `launch`, but is only asserted structurally.

So a provider can pass the entire golden-fixture suite, satisfy [L2]
conformance as written, and still deploy agents that never connect. The layer
the bug lives in is the one the fixtures cannot reach.

## Symptoms, so others can recognise it

Two runtimes, two different signatures, one cause:

- **goose** — `goose acp` blocks on stdin, so the process lingers. `ps` shows a
healthy agent, the worktree/pod looks fine, and it never responds to anything.
- **buzz-agent** — exits immediately with nothing driving it, so its terminal
disappears and it looks like a crash with no error.

In both cases Buzz's own view is a successful deploy: `backend_agent_id` set,
`last_error: null`. There is no failure to surface, because from the provider
protocol's perspective nothing failed.

## Suggested fixes

Any one of these would have prevented it, roughly in order of preference:

1. **Have `launch` carry the resolved harness invocation** — e.g. a
`harness_command` field, or make `command`/`args` the full command to exec
with the inner agent already expressed in `env`. Then providers cannot get
it wrong, which is consistent with the stated rationale for the `launch`
block ("A provider MUST NOT reimplement that derivation").
2. **State it in §Launch data**: the provider runs the harness; `launch.command`
and `launch.args` go to `BUZZ_ACP_AGENT_COMMAND` / `BUZZ_ACP_AGENT_ARGS`
(comma-delimited).
3. **Add a fixture** whose expected behaviour exercises the harness layer, so
[L2] conformance means something here.

## Context

Found while building an out-of-tree provider that runs Buzz agents in
[Orca](https://stably.ai) worktrees. Happy to send a docs PR for (2) if that is
useful.

Verified against `main` at `07a3c76`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.