block / block/buzz

buzz-acp: expose channel and sender identity via ACP `_meta` on `session/prompt`

Open
#4,745 0 comments 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

### Problem

`buzz-acp` renders rich event context — channel id, sender pubkeys (hex + npub), event ids, timestamps, thread structure — into the prompt *text* via `format_event_block`. That's great for the model, but any ACP agent that needs this data *programmatically* (multi-tenant agents keying memory or authorization on the sender; bridges routing to per-user backends) has to parse it back out of the prompt string.

That parsing is fragile by construction: the block format is an internal rendering detail, and any wording change silently breaks every agent that scrapes it. It also can't distinguish "the agent was told who sent this" from "the transport asserted who sent this" — the text is inside the model-visible prompt, so a message *quoting* an event block is indistinguishable from the real thing.

### Proposal

Attach the same facts, structured, to the `session/prompt` request's `_meta` field — which the ACP spec defines on every protocol type for exactly this purpose, and which buzz-acp already uses in several places (`_meta.systemPrompt`, `_meta.sessionTitle`, `_meta.goose.activeRunId`, `_meta.steering.supported`).

Sketch (names open to bikeshedding; nesting under a `buzz` key to keep the root clean, matching the existing `_meta.goose.*` pattern):

```jsonc
{
"method": "session/prompt",
"params": {
"sessionId": "…",
"prompt": [ /* unchanged rendered text blocks */ ],
"_meta": {
"buzz": {
"channelId": "7f3a2b10-…",
"channelType": "channel", // or "dm"
"events": [
{
"id": "",
"sender": "",
"kind": 9,
"createdAt": 1785840000
}
],
"cancelledEvents": [ /* same shape, for Steer/Interrupt merges */ ]
}
}
}
}
```

The prompt text stays exactly as it is — this is additive metadata, not a rendering change. Agents that ignore `_meta` see no difference.

### Why upstream (rather than every agent parsing)

- The data already exists at the call site (`FlushBatch` has `channel_id` and each `BatchEvent` carries the full event), so the change is small and local to where `session/prompt` is built.
- Every ACP agent behind Buzz benefits — memory partitioning, per-sender policy, dedup by event id, thread-aware routing — without each one reinventing a scraper against an unstable format.
- It gives agents a *transport-asserted* identity channel, distinct from model-visible text, which matters for anything security-adjacent.

Happy to send a PR if the shape looks reasonable.

*Context: we're building [muxi-ai/acp-bridge](https://github.com/muxi-ai/acp-bridge), which presents a remote MUXI formation as an ACP agent, with Buzz as the first host — the sender/channel identity drives per-user memory partitioning on our side.*

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.