buzz-acp: no way to choose the agent's toolset for bridge sessions — operators must patch the agent's source instead
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
*Reported by Claude Code, with the account owner's permission, from a self-hosted deployment.*
## Summary
buzz-acp never sends a toolset selection in `session/new`, so the agent always
receives its default ACP toolset. When an operator needs a different tool list
for bridge sessions — dropping tools that cannot work in the deployment, or
adding one the default omits — the only remaining option is to **patch the
agent's source**, which then has to be re-applied after every agent update.
A `BUZZ_ACP_AGENT_TOOLSETS` env var, passed through to the session, would make
this a configuration choice.
## Why this bites
The agent side already supports it. In Hermes (hermes-agent), the ACP session
builder takes a toolset list and only falls back to a default when the client
sends nothing:
```python
def _expand_acp_enabled_toolsets(toolsets=None, mcp_server_names=None):
for name in list(toolsets or ["hermes-acp"]): # <- client could choose
```
buzz-acp has no corresponding knob — `grep -rn toolset crates/buzz-acp/src/`
returns nothing — so that parameter is unreachable from the harness.
In our deployment the default ACP toolset advertises browser tools that cannot
work (no CDP in the sandbox). The model repeatedly chose them, burned entire
turns failing on them, and never called the tool that actually delivers a
reply. We ended up maintaining a local patch to the agent's toolset table:
remove the dead browser/vision entries, add the scheduler tool. It works, but
it is a source patch to a dependency, re-applied on every update — exactly the
kind of thing an env var would eliminate.
Notably the agent's own config-level `disabled_toolsets` does **not** help
here: an explicit ACP tool list wins over it, and it operates on whole bundles
rather than individual tools.
## Proposal
```
BUZZ_ACP_AGENT_TOOLSETS=my-bridge-toolset[,another]
```
- Defaults to unset → current behaviour exactly (agent picks its default), so
this is backward compatible.
- When set, pass the list through in `session/new`.
- Same shape as the existing `BUZZ_ACP_AGENT_COMMAND` / `BUZZ_ACP_AGENT_ARGS`
pattern: the harness already parameterises *how* the agent is launched; this
parameterises *what it is allowed to do* in bridge sessions.
Worth noting it is also a safety-relevant knob, not only convenience: an
operator running a bridge in a shared channel may want a deliberately narrower
tool list there than in an interactive session, and today there is no supported
way to express that from the harness side.
## Environment
- Self-hosted relay (docker compose bundle), buzz-acp as a systemd service,
Hermes as the ACP agent, two bridge instances with different models.
## Related
- #6017 (`BUZZ_ACP_AGENT_ARGS` delimiter) — same area, also about making
agent launch configurable rather than requiring workarounds.
Contributor guide
Research direction
Start by searching crates/buzz-acp/src for session/new handling and the existing BUZZ_ACP_AGENT_COMMAND / BUZZ_ACP_AGENT_ARGS configuration pattern. Confirm that an unset variable preserves current agent-default behavior, while a comma-separated value is passed through as the session toolset selection.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100