Skip to content

hive-acp: run a harness in a container, as a Buzz harness - #4

Merged
unforced merged 1 commit into
Unforced-Dev:mainfrom
unforcedagi:hive-acp
Jul 29, 2026
Merged

hive-acp: run a harness in a container, as a Buzz harness#4
unforced merged 1 commit into
Unforced-Dev:mainfrom
unforcedagi:hive-acp

Conversation

@unforcedagi

Copy link
Copy Markdown
Contributor

Moves hive from the "where to run" seam to the "harness" seam.

Why the seam matters

As a backend provider, hive competes with Buzz's own notion of location — which is exactly why buzz-backend-hive had to reimplement remote deployment over ssh. As a harness, harness=hive composes with whatever Buzz already does about location: local, a remote provider, or this box acting as a provider for a laptop.

Location stays Buzz's axis. The environment becomes hive's.

Buzz v0.5.0 added BYOH (block/buzz#2773), so a Tier-3 custom harness is just a JSON file in custom_harnesses/ — no fork required. examples/buzz-custom-harness.json has one ready to edit.

It deliberately does not parse the protocol

It could — intercept initialize, route by session id, gain mid-conversation harness switching. That's a real feature and it isn't this one.

Everything that would justify parsing is decided before the first byte moves: the agent from HIVE_AGENT, its harness from its spec, its credentials and MCP servers from hived. Nothing is left to choose, so there's nothing to intercept — and a proxy that re-frames JSON-RPC it doesn't need to read is a proxy that can corrupt a stream it was only meant to carry.

ACP's framing is also not something to assume. A byte pipe is correct whether messages are newline-delimited or length-prefixed, and stays correct when that changes. When routing between several backends is wanted, this becomes a real router. Until then, being a pipe is the feature.

A detail worth keeping

The harness is read from the spec, not from the environment, because the spec is what hived reconciled the container from. Taking it from the environment lets the two disagree — and the symptom is a harness that starts, answers initialize, and has none of the credentials the container was built for.

Verified against a real container

A real ACP initialize proxied through to claude-agent-acp 0.63.0, which answered with full capabilities — including:

"mcpCapabilities": { "http": true, "sse": true }

That's the thing Buzz itself cannot configure (its McpServer is stdio-only) and that hive mcp (#3) now provides. The harness side was ready all along.

Also checked: missing config exits 78 (EX_CONFIG) with an actionable message rather than hanging, and all logging goes to stderr — one stray line on stdout would corrupt the ACP stream and present as a harness that connects then ignores everything.

108 tests pass.

Follow-ups, not in this PR

🤖 Generated with Claude Code

https://claude.ai/code/session_01Gw5rgVt1CQ8EYrLpZtQjdM

Moves hive from the "where to run" seam to the "harness" seam.

As a backend provider, hive competed with Buzz's own notion of location —
which is why buzz-backend-hive had to reimplement remote deployment over
ssh. As a harness, `harness=hive` composes with whatever Buzz already does
about location: local, a remote provider, or this box acting as a provider
for a laptop. Location stays Buzz's axis; the environment becomes hive's.

Buzz v0.5.0 added BYOH (block/buzz#2773), so a Tier-3 custom harness is a
JSON file in `custom_harnesses/` — no fork required. examples/ has one.

It does NOT parse the protocol, deliberately. Everything that would
justify parsing is decided before the first byte moves: the agent from
HIVE_AGENT, its harness from its spec, its credentials and MCP servers
from hived. Nothing is left to choose, so there is nothing to intercept —
and a proxy that re-frames JSON-RPC it does not need to read can corrupt a
stream it was only meant to carry. ACP framing is also not something to
assume; a byte pipe stays correct whether messages are newline-delimited
or length-prefixed. When routing between several backends is wanted, this
becomes a real router; until then being a pipe is the feature.

The harness comes from the SPEC rather than the environment, because the
spec is what hived reconciled the container from. Reading it from the
environment would let the two disagree, and the symptom would be a harness
that starts, answers initialize, and has none of the credentials the
container was built for.

Verified against a real container: a real ACP initialize proxied through
to claude-agent-acp 0.63.0, which answered with full capabilities —
including mcpCapabilities {http, sse}, the thing Buzz itself cannot
configure and `hive mcp` now provides.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gw5rgVt1CQ8EYrLpZtQjdM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants