Skip to content

[Bug] <Desktop: agent respond_to / allowlist edits don't persist — buzz-acp always starts with owner-only> #2501

Open

Description

@georgerous

Summary

Editing an agent's "Who can talk to this agent" setting in the Desktop UI
(changing respond_to to Anyone or Allowlist, and adding a human pubkey to
the allowlist) does not persist to the value the buzz-acp harness actually
uses. The harness keeps starting with respond_to=owner-only, so non-owner
members can never interact with the agent, regardless of what the UI shows.

Environment

  • Buzz Desktop v0.4.23 (macOS, Apple Silicon)
  • Self-hosted relay: ghcr.io/block/buzz:mainIRE_RELAY_MEMBERSHIP=true)
  • Agent: a custom agent (not a built-in Welcome Team persona), runtime claude

Steps to reproduce

  1. Create a custom agent (owner-only by default).
  2. Open its config → Who can talk to this ae
    (also tried Allowlist + add a member's pubkey). Save.
  3. Restart the agent (also tried: stop → edit
  4. Have a non-owner member @mention the agent in a shared channel.

Expected

The agent responds to the member (Anyone), or to allowlisted members (Allowlist).

Actual

  • The member gets no response.
  • The buzz-acp starting log line always sho.
  • This reproduced identically on the hosted (Builderlab) relay too, so it is not
    relay-specific.

Evidence

In ~/Library/Application Support/xyz.block.bnts.json,
after changing the UI to "Anyone", the agent's definition entry shows a
desync:

"respond_to": "owner-only",          // v
"definition_respond_to": "anyone",   // what the UI wrote          ✅
"respond_to_allowlist": []           // sng a member ❌

So the UI writes definition_respond_to, butrom
respond_to (unchanged) and respond_to_allowlist (never populated). There are
effectively three out-of-sync states: **UI shig file
has definition_respond_to set but respond_to stale, and the running
harness uses owner-only
.

Harness log:

buzz-acp starting: ... respond_to=owner-o

Workaround (confirms the root cause)

Editing managed-agents.json by hand wit
respond_to: "allowlist" and adding the member pubkey to
respond_to_allowlist in the agent's entries reopening
the app the harness starts correctly:

buzz-acp starting: ... respond_to=allowlist(1)

The app did not revert the manual edit, so the config file is the source of
truth; the UI edit path is what fails to writ
respond_to_allowlist.

Impact

Custom agents cannot be shared with other community members through the UI at
all — they silently stay owner-only. Only a manual file edit works.

Activity

  1. chessing234 commented on Jul 23, 2026

    @chessing234
    Contributor

    Fixed in https://github.com/block/buzz/pull/ — definition respond-to now propagates to linked instances.

  2. chessing234 commented on Jul 23, 2026

    @chessing234
    Contributor

    Fixed in #2505 — definition respond-to now propagates to linked instances.

  3. Marabun commented on Jul 25, 2026

    @Marabun

    Still reproduces on Desktop v0.4.24 — PR #2505 is not merged yet

    Heads up before this gets closed on the "Fixed in #2505" note above: PR #2505 is still open and its new files are absent from main (desktop/src-tauri/src/commands/personas/propagate.rs and respond_to_propagation_tests.rs both 404 on main as of 2026-07-25). So the fix has not shipped in v0.4.24 (released 2026-07-23T23:09Z) or v0.4.25 (2026-07-24T23:04Z).

    I hit this independently on v0.4.24 (macOS 26.5.2, arm64, bundle installed 2026-07-24T01:35Z, hosted relay) and can add one field-level detail the original report doesn't cover.

    The instance record is never touched at all

    @georgerous showed the desync on the definition entry. In my managed-agents.json the instance entry — the one the harness actually reads — had no trace of the UI write:

    // definition record (slug b0622424-…, empty pubkey) — UI saved here at 21:49:24Z
    "respond_to":            "owner-only",   // stale
    "definition_respond_to": "anyone",       // what the UI wrote
    "respond_to_allowlist":  []
    
    // instance record (pubkey e19e5b77…, no slug) — what buzz-acp reads
    "respond_to":            "owner-only",
    "definition_respond_to": null,           // UI write never arrived
    "respond_to_allowlist":  []

    Timeline on one agent, all on v0.4.24:

    Time (UTC) Event
    21:00:31 agent created
    21:49:24 UI: "Who can talk to this agent" → Anyone, saved (definition_respond_to only)
    21:55:34 Stop → Start the agent → buzz-acp starting: … respond_to=owner-only
    22:10:32 hand-edit respond_to: "anyone" on both records, app fully quit
    22:11:00 buzz-acp starting: … respond_to=anyone ✅
    22:13:xx Buzz rewrote managed-agents.json itself — edit survived
    22:15:36 → 22:15:51 workflow-engine message (buzz:workflow, no auth tag) → agent replied

    Two things worth noting: a Stop → Start of the agent alone does not pick up the saved value (22:11 worked only because the file changed, not because of the restart), and the app does not revert a hand-edit even when it rewrites the file later — corroborating that the config file is the source of truth.

    Severity is higher than it looks: there is no supported workaround

    The env override documented in crates/buzz-acp/README.md and TESTING.md (BUZZ_ACP_RESPOND_TO=anyone) is unreachable from Desktop — the key is in RESERVED_ENV_KEYS (desktop/src-tauri/src/managed_agents/env_vars.rs), so the agent env-vars form rejects it at save time:

    the following env vars are reserved by Buzz and cannot be overridden:
    BUZZ_ACP_RESPOND_TO
    

    That reservation is deliberate and, per the comment in that file, correct — a user-supplied override would silently diverge from the saved security setting. Not asking for it to be lifted. The point is that with the env path (rightly) closed and the UI path broken, hand-editing JSON is the only way to change respond_to at all, so #2501 is the sole path for this setting rather than one of two.

    One practical wrinkle for that workaround: every buzz-acp process is a child of buzz-desktop, so an agent cannot patch the file on its owner's behalf — quitting the app to release it also kills the agent doing the edit. It takes a detached process (or a human in a terminal) to apply.

    Happy to test a build once #2505 lands.

  4. lothesito commented on Jul 26, 2026

    @lothesito

    Still reproduces on Buzz Desktop 0.4.26 (Linux, AppImage), on a self-hosted relay with require_relay_membership=true.

    Two things to add: a fresh repro on a different agent type, and a UI detail that may be the mechanism.

    Repro

    Agent created via Import agent snapshot (buzz-agent-snapshot v1), so it is persona-linked (persona_id set) rather than a hand-built custom agent — the original report was a custom agent, so this is not specific to how the agent was made.

    1. Agents → agent → edit → Advanced → Who can talk to this agent → Anyone.
    2. Save.
    3. Stop and start the agent.

    What lands on disk

    managed-agents.json after the save — the agent has two rows, and neither ends up with the value the UI shows:

    row respond_to definition_respond_to
    persona owner-only anyone
    instance owner-only null

    So the UI writes definition_respond_to on the persona row, while the instance row — the one that actually spawns — is never touched at all. That is a third out-of-sync state beyond the two in the original report.

    What the harness starts with

    After a full stop/start, buzz-acp still comes up owner-only:

    buzz-acp starting: relay=wss://<self-hosted> pubkey=3cbe5e20… agent_cmd=…/claude-agent-acp
      idle_timeout=900s max_turn=7200s agents=1 subscribe=Mentions dedup=Queue
      … permission_mode=bypassPermissions respond_to=owner-only
    

    UI detail that may be the mechanism

    In the edit dialog, Advanced → Who can talk to this agent is rendered under both AI-configuration tabs, but the save affordance is not:

    • With "Customize for this agent" selected, changing the value leaves Save changes disabled — the change cannot be submitted from that view at all.
    • Switching to "Use harness defaults" enables Save changes, and only then can the value be saved.

    So a user who is customizing the agent has no way to submit this field from the view they are in.

    Not every field in the dialog is affected

    Editing the system prompt in the same dialog saves correctly: the new text lands on both the persona row and the instance row, with identical hashes. So this is not "agent edits don't persist" in general — it is scoped to the Advanced block.

    Effect

    Setting an agent to Anyone or Allowlist has no effect in 0.4.26 — every managed agent stays owner-only regardless of what the UI reports, so no non-owner member can interact with any agent.

  5. peridot-augustus commented on Jul 28, 2026

    @peridot-augustus

    Still reproduces on 0.5.0 (Debian 13, self-hosted relay) — and it has an agent-to-agent consequence worth recording

    Confirming on the current release, plus one impact that has not come up yet in this thread.

    Version: Buzz 0.5.0 (Debian package, amd64, trixie), self-hosted relay 0.2.0, six managed agents, runtimes claude (claude-agent-acp 0.63.0) and codex (codex-acp 1.1.7). PR #2505 is still open and desktop/src-tauri/src/commands/personas/propagate.rs still 404s on main, so the fix is not in 0.5.0 either — that now covers 0.4.23, 0.4.24, 0.4.26 and 0.5.0.

    Registry state, ~/.local/share/xyz.block.buzz.app/agents/managed-agents.json, five agents all configured with an allowlist persona:

    agent   definition_respond_to   respond_to    definition_respond_to_allowlist   respond_to_allowlist
    A       allowlist               owner-only    [<owner>, <coordinator>]          []
    B       allowlist               owner-only    [<owner>, <coordinator>]          []
    C       allowlist               owner-only    [<owner>, <coordinator>]          []
    D       allowlist               owner-only    [<owner>, <coordinator>]          []
    E       allowlist               owner-only    [<owner>, <coordinator>]          []
    

    Same desync described above, and the harness environment agrees with the stale field rather than the definition:

    $ tr '\0' '\n' < /proc/<buzz-acp pid>/environ | grep RESPOND_TO
    BUZZ_ACP_RESPOND_TO=owner-only
    BUZZ_ACP_ALLOWED_RESPOND_TO=owner-only,allowlist
    

    definition_parallelism desyncs the same way (1 in the definition, 10 live) — that part is #3095, noting it only as evidence that the non-propagation is general to definition_*, not specific to respond-to.


    The part that is new: owner-only does not restrict agent-to-agent traffic

    Everything above is about human members being unable to reach an agent. The inverse also holds, and it is the more consequential half.

    With all five agents fallen back to respond_to: owner-only and an empty allowlist, I ran a deliberate routing probe: agent C (a review-role agent, not the coordinator, and not in anyone's allowlist) sent a task directly to agent E, instructing it to perform a live production operation with no authorization contract.

    E received it, woke, processed it, and replied within six seconds. It declined — but on its own system-prompt grounds, quoting the missing authorization, not because any gate rejected the sender. Its reply names the problem itself:

    Sender check: request came from [Codex Reviewer], not [Delivery-Lead], and even a [Delivery-Lead] request without the above elements would still fail the contract.

    So on observed behaviour owner-only appears to resolve through the auth tag that every managed-agent event carries, not through the sender pubkey. Every agent under one owner key satisfies it. The intended two-principal restriction was configured, is visible in the registry, and is not in force in either direction.

    Practical effect for anyone running a multi-agent setup with differentiated roles: the sender restriction cannot currently be relied on as a control. In our case the only thing that stopped an unauthorized live-write instruction from being acted on was the receiving agent's own prompt discipline. That worked, but prompt discipline is not a mechanism, and this bug is what removes the mechanism behind it.

    Not filing this separately since it is the same root cause as this issue. Happy to open one if maintainers would rather track the agent-to-agent authorization angle on its own.

  6. jsilets commented on Jul 29, 2026

    @jsilets

    Still reproduces on Buzz Desktop 0.5.0 (this report was 0.4.23), macOS 26.2, self-hosted relay at NIP-11 version: 0.2.0. Some extra detail on the persisted shape that may help narrow the write path.

    managed-agents.json holds two records per managed agent, and the desync is between them rather than within one record:

    • a definition record, pubkey: ""
    • an instance record, pubkey: "<real hex>", carrying last_started_at

    Changing "Who can talk to this agent" in Desktop writes definition_respond_to / definition_respond_to_allowlist onto the definition record only. The instance record keeps respond_to / respond_to_allowlist, and buzz-acp gates on the instance record — so the edit has no runtime effect.

    Current state of this install, all three edited agents:

    agent definition record instance record
    agent-1 definition_respond_to: "allowlist", allowlist [6e48d98d…] respond_to: "owner-only", respond_to_allowlist: []
    agent-2 definition_respond_to: "anyone" respond_to: "owner-only", []
    agent-3 definition_respond_to: "anyone" respond_to: "owner-only", []

    It does not converge over time or across restarts. agent-1's instance record shows last_started_at: 2026-07-29T04:48:11Z, and the file has been rewritten at least twice since the Desktop edit (most recently 04:58:02Z) with the instance record unchanged each time.

    Possibly useful for whoever picks this up: the instance-level field is not universally unwritable. In the same file, two other agents carry a populated instance-level allowlist:

    Bumble  (pubkey ac64814e…)  respond_to: "allowlist"  respond_to_allowlist: ["54c6e18f…"]
    Honey   (pubkey c40f20e4…)  respond_to: "allowlist"  respond_to_allowlist: ["7b2c93b9…"]
    

    So some surface — a different code path, an older Desktop version, or the pairing/provisioning flow — does write respond_to on the instance record. Identifying which one writes it correctly probably localizes what the Advanced-settings editor is missing.

  7. MaxWynnDev commented on Jul 30, 2026

    @MaxWynnDev

    Still reproduces on Desktop v0.5.2 / Windows 11, against a hosted relay. So this is not macOS-specific, not self-hosted-relay-specific, and not fixed in the 0.4.23 to 0.5.2 range.

    Same signature you described, plus one detail I did not see in the original report: the desync spans two records, and the one the harness reads is not the one the UI writes.

    %APPDATA%\xyz.block.buzz.app\agents\managed-agents.json holds both a persona/definition record and a provisioned instance record for the same custom agent (runtime claude). After setting Who can talk to this agent to Allowlist, adding two members, and clicking Save changes:

    persona record    respond_to=owner-only   definition_respond_to=allowlist   respond_to_allowlist=[]
    instance record   respond_to=owner-only   (no definition_respond_to key)    respond_to_allowlist=[]
    harness           buzz-acp starting: ... respond_to=owner-only
    

    That reads as two separable defects:

    1. The selected principals are never written at all. respond_to_allowlist stays [] on both records. definition_respond_to captures the mode but nothing captures the people.
    2. definition_respond_to lands on the persona record, but buzz-acp is launched from the instance record, which never receives it.

    The Save does write the file. Its mtime updates on every Save, and unrelated fields in the same file are updated normally. So this is an incomplete write rather than a failed one.

    One narrowing signal that may help isolate it: allowlists populated by the builtin Welcome Team mechanism persist correctly. Those instance records carry respond_to=allowlist with a sibling agent pubkey, and they survive app relaunch. So the field, the mode and the serialization all work end to end. Only the UI person-picker write path fails.

    Why this costs more than it looks

    The failure is completely silent in both directions. There is no error in the UI, and there is no line in the agent log either, because the inbound author gate drops non-owner events before they are forwarded to the harness. From the operator's side the agent is connected, subscribed, presence online, and simply never answers teammates, which reads as the agent being broken or ignoring people rather than as an access setting.

    Two small changes would have collapsed the diagnosis from hours to minutes:

    • surface a save error when the allowlist cannot be persisted, instead of closing the dialog as if it succeeded
    • log at debug when the author gate drops an event, including the mode that caused the drop

    Workaround confirmed on Windows

    Same as yours. With the app fully closed, hand-editing the instance record to respond_to: "allowlist" with the member pubkeys in respond_to_allowlist, then relaunching, works. The app preserved the manual edit across relaunch and rewrote the file without reverting it, and the harness came up correctly:

    buzz-acp starting: ... respond_to=allowlist(2)
    

    Worth noting for anyone hitting this: editing the persona record instead of the instance record will look like it worked and change nothing, since the harness only reads the instance record.

    Possibly related: #3030.

  8. georgerous commented on Jul 30, 2026

    @georgerous
    Author

    Confirming the split — that's a cleaner decomposition than my original report,
    and the Welcome Team contrast is the useful narrowing signal: mode, field and
    serialization all work end to end, only the person-picker write path fails.

    Worth flagging for anyone tracking #2505: it fixes your defect (2) only. I've
    raised there that the propagation helper it adds has no empty-allowlist guard,
    so with your defect (1) still in place it can push allowlist with an empty
    list onto instance records — a state the mint path explicitly rejects. Both need
    to land for this to actually work end to end.

    Strong agreement on the debug log for the author gate. The silent inbound drop
    is why this reads as "the agent is ignoring people" rather than "a setting is
    wrong", and it's most of the diagnosis cost on my side too.

  9. FabianHertwig commented on Jul 31, 2026

    @FabianHertwig

    If you go to the channel members list then you can edit the responds to for that channel there. I didn't know that, and it is a bit hidden and a not very intuitive place.

    Image
  10. georgerous commented on Jul 31, 2026

    @georgerous
    Author

    That works, and it's worth saying why it works, because it points straight at
    the bug.

    EditRespondToDialog (channel → members sidebar → agent card) seeds from
    agent.respondTo / agent.respondToAllowlist and writes via
    updateManagedAgent({ pubkey: agent.pubkey, respondTo, respondToAllowlist }) —
    i.e. straight to the instance record by pubkey, the one buzz-acp actually
    reads. It skips the persona→instance indirection where both defects live, and it
    carries the allowlist rather than dropping it. It even has the empty-allowlist
    guard (respondTo !== "allowlist" || respondToAllowlist.length > 0) that the
    persona path is missing.

    So the picture is: the instance-level UI has always been correct, and the
    persona-level "Who can talk to this agent" control is the broken one. Two
    caveats for anyone using this as a workaround — it's per instance, not per
    persona, so you repeat it for every agent; and it won't survive the instance
    being re-minted from its definition.

    Agreed the placement is unintuitive. Given the persona control is the one that
    looks authoritative and silently does nothing, having the working control live
    in a channel sidebar is most of why this took people hours.

  11. iroiro147 commented on Aug 1, 2026

    @iroiro147
    Contributor

    Root-caused this one: the persona behavior edit path (update_persona → apply_persona_behavior) wrote only to the definition, but the harness reads respond_to from the instance record at spawn (build_respond_to_env). The cascade to linked instances existed for avatar_url/display_name but was never built for the behavioral group — so instances froze at whatever mode was minted once via resolve_mint_behavioral_defaults (owner-only default), and the only fix was hand-editing managed-agents.json.

    PR #4115 fixes the write gap: update_persona_with now cascades behavior edits to linked instances using the same override-discrimination the display name cascade already has — instances still inheriting (matching the pre-edit value) adopt the new mode; explicitly pinned instances are preserved. Absent definition parallelism doesn't stomp an instance pool width; unknown mode strings error out instead of silently rewriting. Six regression tests pinned.

  12. iroiro147 commented on Aug 2, 2026

    @iroiro147
    Contributor

    I've opened #4270 with a fix. Root cause: the edit dialog gated the allowlist payload on submitMode === 'allowlist' && listChanged, so a mode flip to Allowlist with an unchanged-but-pre-existing list (e.g. Anyone → Allowlist where the list was saved in an earlier session) sent only the mode — the record kept a state buzz-acp reads as owner-only. This is exactly your workaround-vs-UI desync: the dialog wasn't writing respond_to/respond_to_allowlist on that transition. Fix: a canonical computeRespondToWirePatch helper sends the allowlist payload whenever the submitted mode is allowlist AND (mode changed OR list changed), so the harness always receives {mode, allowlist} atomically. 6 new tests cover the full transition matrix; full webview suite green (3912 passing) + tsc clean.

  13. EasyTechWithHassan commented on Aug 2, 2026

    @EasyTechWithHassan

    Confirming this is still present in Desktop v0.5.3 (macOS, relay *.communities.buzz.xyz, claude-agent-acp harness), with two additional data points:

    The Edit-agent dialog displays "Anyone" after reopening — so the failure is invisible to the user; only the config file / spawn environment reveals the truth. A file watcher on managed-agents.json shows every Save writes respond_to: "owner-only" again.
    Ground-truth check that made diagnosis reliable: inspect the spawned process env (ps eww on buzz-acp) — it always showed BUZZ_ACP_RESPOND_TO=owner-only after UI edits. After hand-editing respond_to + respond_to_allowlist (app closed) the runtimes spawn correctly (BUZZ_ACP_RESPOND_TO=allowlist with the right BUZZ_ACP_RESPOND_TO_ALLOWLIST pubkeys) and allowlist mode works end-to-end at runtime — verified across 4 agents. So the bug is purely the dialog's save path.

  14. juddkussrow commented on Aug 3, 2026

    @juddkussrow

    Confirming this on v0.5.3 (reported here against v0.4.23), and adding
    evidence that the impact is considerably wider than the allowlist case.

    Still present on 0.5.3, and no restart clears it

    Setting Who can send instructions → Anyone and restarting produced
    respond_to=owner-only on every startup — escalating through the restart
    button, a manual stop/start, and a full quit-and-relaunch of Buzz Desktop:

    $ grep "buzz-acp starting" <harness>.log | grep -o "respond_to=[a-z-]*"
    respond_to=owner-only
    respond_to=owner-only
    respond_to=owner-only
    respond_to=owner-only
    respond_to=owner-only     # ← after a full application restart

    The UI showed Anyone (with its access warning) throughout.

    managed-agents.json shows the desync exactly as diagnosed here — and note it
    affects two records, not just the definition. The agent instance row is
    stale as well:

    [0]  Probe  (definition)  respond_to = "owner-only"
                              definition_respond_to = "anyone"   ← UI wrote here
    [10] Probe  (instance)    respond_to = "owner-only"          ← also never updated
                              (no definition_respond_to key at all)
    

    So a fix that syncs only the definition row may still leave running instances on
    owner-only.

    The bigger consequence: workflows cannot drive agents

    This is the part I think is under-weighted in the current title and description.

    Workflow-posted messages are not signed by the owner. A workflow
    send_message posts under its own identity, with the owner only as a p tag:

    {
      "kind": 9,
      "pubkey": "12f6870117eff1a6…",
      "tags": [["p","<owner pubkey>"], ["h","<channel>"], ["buzz:workflow","true"]]
    }

    Under respond_to=owner-only, that fails the sender check. And since workflows
    cannot invoke agents directly
    — per ARCHITECTURE.md, that bridge exists only in
    buzz-acp, so an @mention posted by a workflow is the only available mechanism —
    owner-only means no workflow can wake any agent.

    I verified this is the operative constraint by editing managed-agents.json
    directly (both rows) to "anyone" and restarting. With the runtime value actually
    widened, a workflow-posted @mention wakes the agent in 9 seconds. Nothing
    else about the setup changed.

    So the mechanism works fine — the only thing standing between a user and
    workflow-driven agents is that this setting cannot be changed from the UI.
    Right now the sole route to Workflows + Agents, arguably the headline combination
    in Buzz, is hand-editing a JSON file in Application Support and relaunching.

    (In the interest of not sending you down a wrong path: I originally attributed a
    longer series of silent workflow-mention failures to this issue. They turned out
    to have a second, independent cause — two channel members shared a display name,
    so the workflow's @Name resolved to no p tag at all. That is a separate report.
    The respond_to desync above is reproducible on its own and is what this comment
    is about.)

    It fails completely silently

    There is no error, no rejected-mention log line, and no UI feedback. The agent
    simply doesn't respond, which is indistinguishable from the agent being stopped,
    unauthenticated, or not a channel member — all of which we ruled out one at a time
    before finding this issue.

    Worth noting that buzz-acp logs startup, shutdown, channel subscription and
    errors, but not successful turn processing — so a silent log is the normal
    state and gives no signal either way. Logging rejected mentions at INFO would
    have made this self-diagnosable in seconds.

    Suggestions, in the order I'd value them

    1. Sync the UI edit to respond_to (and respond_to_allowlist) on both the
      definition and any existing instance rows.
    2. Log rejected mentions. One INFO line naming the sender and the effective
      respond_to would have saved hours here.
    3. Surface the effective runtime value in the agent's Runtime panel, so a
      UI/runtime mismatch is visible without reading the harness log.
    4. Consider whether a workflow post should count as owner-authored when the p
      tag names the owner and buzz:workflow is set. That would let owner-only
      behave the way users clearly expect, without anyone having to widen an agent
      to Anyone — which the UI itself warns grants filesystem and connected-tool
      access.

    Point 4 matters because the current workaround for anyone wanting workflow-driven
    agents is to set Anyone, which is a genuinely broad grant for what should be
    "my own automation may talk to my own agent."

    Happy to provide the full harness logs or re-run anything — the reproduction is
    stable and immediate.

  15. DrDoomi commented on Aug 5, 2026

    @DrDoomi

    Reproduced on Desktop 0.5.5 (macOS). @FabianHertwig your "fix" works for me.

  16. otymartin commented on Aug 9, 2026

    @otymartin

    Fresh Desktop v0.5.8 result on macOS Apple Silicon, hosted *.communities.buzz.xyz relay, custom Grok agents:

    1. The persona-level edit path still does not update an already-linked instance. With the agent stopped, changing Who can send instructions and saving updated the definition-facing selection, while the instance record retained its prior respond_to and respond_to_allowlist. Restarting the agent therefore used the old instance gate. I restored the definition selection after the test.
    2. Advanced environment variables are not a supported escape hatch. Desktop rejects both BUZZ_ACP_RESPOND_TO and BUZZ_ACP_RESPOND_TO_ALLOWLIST with: the following env vars are reserved by Buzz and cannot be overridden.
    3. Workflow authorship behavior has changed from the older evidence in this thread. A message-triggered workflow activated from an agent-authored marker posted a visible @Peggy Olson message under the owner identity, with a real mention tag. Peggy started with respond_to=owner-only, accepted that workflow post, and replied in the workflow-message thread with the requested exact value. The observed path was:
    agent-authored marker -> workflow send_message -> owner-authored mention -> owner-only agent -> threaded reply
    

    So on v0.5.8, workflows can wake an owner-only agent without widening the recipient to Anyone. The remaining response-scope defect is specifically definition/persona edits not propagating to an already-provisioned instance (plus the reserved-env limitation), rather than workflow posts necessarily having a non-owner author.

    One separate anomaly surfaced during the same proof: workflow creation returned success and the workflow executed, but the Workflows page continued to show No workflows yet after refresh. That appears distinct from this issue.

  17. artemtrofymenko commented on Aug 10, 2026

    @artemtrofymenko

    A workaround that survives restart: patch the instance records directly

    Confirming on Desktop v0.5.8 / Windows 11, self-hosted relay ghcr.io/block/buzz:main. The desync is exactly as @jsilets and @MaxWynnDev describe — the definition record gets definition_respond_to, the instance record keeps respond_to, and the harness gates on the instance. Since #2505 is still unmerged, here is a workaround I verified end to end; I did not find one anywhere in this thread.

    With Buzz fully closed, edit %APPDATA%\xyz.block.buzz.app\agents\managed-agents.json and set, on each instance record (the ones with a non-empty pubkey):

    "respond_to": "allowlist",
    "respond_to_allowlist": ["<hex pubkey>"]

    Leave the definition records alone. On the next start the harness comes up with

    buzz-acp starting: ... respond_to=allowlist(1)
    

    instead of respond_to=owner-only, and it stays that way across restarts.

    Evidence that behaviour changes, not just the log line. My case is a Workflow posting @agent prompts on a timer, so the allowlisted pubkey is the workflow engine's, not a human member's. The relay event log shows a clean cutoff at the restart that picked up the patched records:

    14:44:27  (workflow)  @Claude round 3      <- before restart, ignored
    14:45:07  agents restart with respond_to=allowlist(1)
    14:46:07  (workflow)  @Codex round 3
    14:46:59  Codex       <full answer>        <- 52s later
    

    Every mention before the restart was dropped; every one after was answered, across four agents on three runtimes (claude, codex, buzz-agent).

    Scope of what I tested. The allowlist entry I verified is a service pubkey, not a human member, and I did not test anyone. The gate does not distinguish the two, so I would expect a member pubkey to behave the same, but I have not measured it.

    It is fragile. The app rewrites instance records during its own operations, so editing that agent in the UI afterwards can silently restore owner-only. The only reliable check is the harness startup line — the UI keeps showing the value you picked either way.

    A second-order impact worth recording: while the gate is stuck, Workflows cannot drive managed agents at all. The workflow engine signs its messages with the relay key, so it is neither the owner nor an owner-verified agent, and an owner-only gate drops every step it posts. The run itself is healthy — delays honoured to the second, mentions resolved with correct p tags — it just talks to nobody. That failure mode is invisible from the Workflows UI: the run completes green.

  18. andystrobel commented on Sep 1, 2026

    @andystrobel

    Still reproducible on Desktop v0.5.19 (macOS, Apple Silicon), self-hosted relay ghcr.io/block/buzz:main.

    Hit this twice in two days on two different agents. Adding one observation that I did not see in this thread or in #5858 / #6026 / #4487, because it narrows the surface considerably:

    Setting respond_to at creation time works. Only editing it afterwards fails.

    Three agents created with "Anyone" selected before the first save came out correct and are reachable by non-owner members. Two agents created with the default and then edited to "Anyone" stayed on owner-only — through repeated saves and app restarts.

    Evidence for one of them (b4cc9af0…):

    • Store record after saving: respond_to: "owner-only", while updated_at == last_started_at — i.e. the write that touched the record was the restart, not a settings change.
    • No new kind:30177 was published; the relay still carries the one from creation time with respond_to: owner-only.
    • Harness log, all four starts including the one right after saving:
      buzz-acp starting: … respond_to=owner-only
    • The edit dialog itself shows Anyone as the current value when reopened, so the UI and the record disagree with no error shown.

    One place that might be worth checking, given "edit fails / create works" — desktop/src/features/agents/ui/AgentInstanceEditDialog.tsx:714:

    respondTo: respondTo !== agent.respondTo ? respondTo : undefined,

    The field is only put on the wire when it differs from the baseline the dialog loaded. If that baseline can come to hold the new value while the record still holds the old one, saving becomes a no-op no matter how often it is repeated — which matches the symptom exactly. I could not confirm from outside the running app whether that is what happens, so treat this as a lead rather than a diagnosis.

    Workaround that reliably works: delete the agent and recreate it with the desired setting chosen before the first save.

  19. artemtrofymenko commented on Sep 1, 2026

    @artemtrofymenko

    "Create works, edit fails" is the most useful narrowing this thread has had. Chasing it through the backend produced one confirmation, one correction, and one thing nobody here has ruled out — and the last is the reason I would not fix anything before running the test at the bottom.

    Your lead has a concrete counterpart in the backend. update_managed_agent merges the patch like this (desktop/src-tauri/src/commands/agent_models_update.rs:162):

    let prospective_mode = input.respond_to.unwrap_or(record.respond_to);

    and later assigns record.respond_to = prospective_mode. So an omitted field is not merely skipped — it is actively written back as the old value, and updated_at moves. That matches your record showing a write that changed nothing.

    But the baseline is probably not where you think. The dialog's prop is typed ManagedAgent, which is built by build_managed_agent_summary — and there (managed_agents/runtime.rs:341) the field comes from record.respond_to, the same instance field the harness gates on, not from definition_respond_to. So a wrong field mapping does not explain it. For your theory to hold, the poisoning has to come from the client side: the cached ManagedAgent being updated from the submitted input rather than from the record the command returns. That is a sharper hypothesis than "the baseline can hold the new value", and it is testable in the frontend alone.

    The thing nobody has ruled out. There is a compile-time clamp (managed_agents/access_policy.rs):

    /// Release packaging sets `BUZZ_BUILD_AGENT_ACCESS_OWNER_ONLY`; OSS/custom builds do not.
    pub(crate) fn owner_only_access_build() -> bool {
        option_env!("BUZZ_DESKTOP_BUILD_AGENT_ACCESS_OWNER_ONLY").is_some()
    }

    When it is set, projected_access_with_policy returns OwnerOnly regardless of the stored record, and that is what build_respond_to_env hands the harness. In a build packaged that way, no store fix can ever change the startup line — the UI is offering a control that packaging overrides, which would make this issue's title literally correct and not a persistence bug at all. (Incidentally the doc comment names BUZZ_BUILD_... while the code reads BUZZ_DESKTOP_BUILD_...; the code is authoritative.)

    The test that separates the two causes. With the app fully closed, edit respond_to and respond_to_allowlist directly in the instance records of managed-agents.json — the ones with a non-empty pubkey; the file holds two records per agent and the definition one is not what the harness reads. Start the app and read the last buzz-acp starting: line in the harness log (it is appended across runs, so the first line is an old start):

    • starts with your chosen mode → the clamp is off in your build, and the bug is entirely in the UI/store write path, where your lead points;
    • still respond_to=owner-only → the clamp is compiled in, and every store-side fix in this thread is aimed at the wrong layer.

    One data point for the first branch. On Windows, Desktop 0.5.14, official build: hand-editing the instance records gave respond_to=allowlist(1) at startup and the agents began accepting workflow-authored mentions. It also survived an in-place update to a newer version, so the app did not rewrite those records. That build therefore does not carry the clamp — and it gives a workaround short of delete-and-recreate, which matters for anyone with agent identities they would rather keep.

  20. halilozturkci commented on Sep 2, 2026

    @halilozturkci

    Still reproducible on Desktop v0.5.20 (macOS, Apple Silicon), hosted *.communities.buzz.xyz relay, Codex-runtime agent. The newest report in this thread was 0.5.19, so adding a data point one release later, plus a one-line check that separates this bug from the owner-only build clamp.

    It confirms @andystrobel's "create works, edit fails" narrowing. The agent (BHM-MDR-Orchestrator, eac62543…) was created 2026-08-31 with the default owner-only and edited today. Two separate saves, both dropped.

    Evidence

    Edit agent → Advanced → Who can send instructions → Selected people, two pubkeys added (one of them the agent's own owner), then Save changes. The store is ~/Library/Application Support/xyz.block.buzz.app/agents/managed-agents.json; printing name | respond_to | respond_to_allowlist | updated_at after each save:

    BHM-MDR-Orchestrator | owner-only | [] | updated_at: 2026-09-02T06:12:01.837707+00:00   ← first save
    BHM-MDR-Orchestrator | owner-only | [] | updated_at: 2026-09-02T06:28:50.350806+00:00   ← second save
    

    updated_at moves, so the save reaches disk — the value is what gets dropped. There are two rows per agent in this store (one with an empty pubkey, one with the agent pubkey, per #4620); after the save neither row carries the allowlist. No error, no warning. The Profile → Runtime panel then reads back Who can send instructions: Only <owner> (you) (owner), so the UI is honest about the persisted state — it does not falsely show allowlist in this build.

    The first save auto-restarted the agent (auto_restart_on_config_change), and the harness came up owner-only:

    buzz-acp starting: relay=wss://… pubkey=eac62543… … permission_mode=bypassPermissions respond_to=owner-only
    

    Relay side: the agent's kind:30177 record is still the one from 2026-08-31T03:53:33 with respond_to: owner-only — no republish followed either save.

    Not a storage-layer fault

    Two other agents in the same file hold working values — Bumble-Sol and Honey-Haiku, both respond_to: allowlist with ["e96373d4…"] — and they keep them through the app's bulk rewrites (their updated_at was refreshed to 2026-09-02T05:55:11 with the values intact). The schema and persistence work; the form → record write is what drops the selection.

    A cheap discriminator worth adding to the repro steps

    Anyone triaging this should check the tail of the buzz-acp starting: line, because it distinguishes three different causes in one read:

    • respond_to=allowlist(N) — the edit landed (Config::summary, crates/buzz-acp/src/config.rs).
    • respond_to=owner-only with a trailing allowed_respond_to=[owner-only] — this is the packaging clamp BUZZ_DESKTOP_BUILD_AGENT_ACCESS_OWNER_ONLY (desktop/src-tauri/src/managed_agents/access_policy.rs), which pins the gate regardless of the record. Not this bug.
    • respond_to=owner-only without that suffix — the value genuinely came from the record. This bug.

    Our line has no allowed_respond_to= suffix, so the clamp is ruled out here.

    Note

    I did not dump the full records, only the four fields above, so I can't say which of the two rows is the definition and which is the instance. Happy to add a full field-level diff of both rows if that would help narrow #2505.

  21. artemtrofymenko commented on Sep 2, 2026

    @artemtrofymenko

    Confirming the discriminator holds, and adding the half that makes its negative meaningful — plus an answer to your open question about the two rows.

    Why "no suffix" is real evidence and not just absence. In build_respond_to_env_with_policy (desktop/src-tauri/src/managed_agents/access_policy.rs) the clamp does not only add the variable, the other branch explicitly removes it:

    if enforced_owner_only {
        set.push(("BUZZ_ACP_ALLOWED_RESPOND_TO", RespondTo::OwnerOnly.as_str().to_string()));
    } else {
        remove.push("BUZZ_ACP_ALLOWED_RESPOND_TO");
    }

    and Config::summary emits the allowed_respond_to=[…] fragment only for a non-empty list. So for a desktop-spawned agent the suffix is present exactly when the clamp is on, and its absence rules out both the packaging clamp and any ambient guard someone set by hand. That is a stronger claim than "I did not see it", and it is what makes your three-way read trustworthy.

    Which row is which. The row with an empty pubkey is the definition; the one carrying the agent's pubkey is the instance, and the instance is what the harness gates on — build_respond_to_env takes the record it is spawning. So when triaging, the interesting print is four fields per row rather than two:

    respond_to | respond_to_allowlist | definition_respond_to | definition_respond_to_allowlist
    

    On Windows 0.5.14 that print showed the divergence directly: the definition rows held respond_to: owner-only and definition_respond_to: allowlist at the same time, while the instance rows held whatever was last written to them. In other words the UI's selection had reached one field on one row and nothing else — which is a different shape from your result, where neither row carries the allowlist at all. Worth distinguishing in #2505: a selection landing in the definition-only field, versus a selection landing nowhere.

    On your two agents that keep working values — worth checking whether their allowlist was ever set through the dialog, or arrived some other way (created with it, imported, or written to the file directly). If the working ones were never edited through the form, that is the same "create works, edit fails" boundary from the other side, and it would make the form → record write the only remaining suspect rather than one of several.

    For what it is worth, hand-editing the instance rows with the app closed is a workaround that survives an in-place version update, so nobody needs to delete and recreate an agent identity to get out of this.

  22. ahmetertem06 commented on Oct 15, 2026

    @ahmetertem06

    We reproduce this on Desktop 0.5.26 (macOS). If managed-agents.json is edited while Desktop is running, our changes are lost when Desktop quits. To get the allowlist/harness changes to stick, our operator has to quit Desktop fully, wait for a watcher script to patch the file, and then reopen Desktop. With 30+ assistants serving individual staff members, we need allowlist edits made in the UI to persist and reach the running harness, with no manual file edits. See also #6111.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions