Signing out and back in re-provisions the built-in agents with new keypairs — duplicate same-named bots accumulate permanently in channels
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Summary
Each sign-in provisions a fresh set of the built-in agents (`Bumble`, `Fizz`,
`Honey`) with **new keypairs**, rather than reusing the ones that already exist.
The old identities are not removed from channels.
After three sign-out/sign-in cycles, one channel held **nine bot members** — three
copies each of three agents, all sharing display names.
This matters beyond tidiness: an `@mention` that matches two or more members
resolves to **no `p` tag at all**, so the agent is never notified. That failure is
completely silent — reported in **#4814**. This issue is the mechanism that
produces the condition #4814 describes, and it does so without any user error.
## Evidence
`managed-agents.json`, grouped by name:
```
# name created_at slug pubkey is_builtin
1 Bumble 2026-08-02T19:58:20 builtin:… (empty) True ← definition
2 Fizz 2026-08-02T19:58:20 builtin:… (empty) True ← definition
3 Honey 2026-08-02T19:58:20 builtin:… (empty) True ← definition
5 Bumble 2026-08-02T20:01:18 None f990a565 False ┐ cycle 1
7 Fizz 2026-08-02T20:01:17 None b00b07e6 False │
9 Honey 2026-08-02T20:01:18 None 5d60ea0a False ┘
4 Bumble 2026-08-03T02:47:54 None aa218e37 False ┐ cycle 2
6 Fizz 2026-08-03T02:47:53 None 9c2937fa False │
8 Honey 2026-08-03T02:47:53 None 095ae155 False ┘
```
Each batch is created within one second — this is automated provisioning, not
manual creation. Every batch mints a **new keypair** for an agent that already
exists.
**A user-created agent behaves correctly.** `Probe`, which I made myself, has
exactly one definition row and one instance row across the same period. Only the
built-ins duplicate.
## The worse half: the local wipe does not clean the relay
The channel member list for the same channel:
```
3cd8a94f owner
ed87d25a bot ← not present in managed-agents.json
e2ee30d9 bot ← not present in managed-agents.json
0193ba91 bot ← not present in managed-agents.json
eb619269 bot ← not present in managed-agents.json
64a5f4b3 bot ← not present in managed-agents.json
60cdd38d bot ← not present in managed-agents.json
9c2937fa bot ← Fizz, cycle 2
095ae155 bot ← Honey, cycle 2
aa218e37 bot ← Bumble, cycle 2
```
**Six of the nine exist nowhere locally.** They are orphans from earlier cycles:
"Sign out and wipe all data" removed the local rows, but channel membership lives
on the relay and survived.
The wipe dialog is accurate about what it does — *"delete your identity key, all
agent settings, and cached data from this device"* — and silent about what it
doesn't. The practical result is that each cycle adds three permanent bot members
to a channel **and destroys the only local handle for managing them**. There is no
obvious path back from the UI.
Note also that the cycle-1 identities (`f990a565`, `b00b07e6`, `5d60ea0a`) are
present in `managed-agents.json` but are **not** channel members, while six
channel members are absent from the file. The two stores have diverged in both
directions.
## Reproduction
1. Fresh install, sign in. Note the built-in agents' pubkeys and the channel member
list.
2. Sign out via **Sign out and wipe all data**.
3. Sign back in with the same identity key.
4. Compare: three new pubkeys for the same three display names, and the previous
three still listed as channel members.
Repeat for a linear pile-up: 3 cycles → 9 same-named bots.
## Impact
- `@Bumble` in that channel is now three-way ambiguous, so it silently notifies
nobody. Any workflow or user mention targeting a built-in agent fails with no
error, no warning, and no log line.
- The member list becomes unreadable — nine entries, three distinct names.
- Orphaned bots cannot be cleaned up locally, since no local record of them remains.
- Each is a distinct identity on the relay, so this is not purely cosmetic.
## Suggested fixes
1. **Make built-in provisioning idempotent** — key it on the built-in slug
(`builtin:…`, already present on the definition rows) and reuse the existing
instance rather than minting a new keypair.
2. **Reconcile on sign-in**: if an identity for a built-in slug already exists as a
channel member, adopt it instead of creating a sibling.
3. **Say what wipe does not cover.** The dialog should state that channel
memberships already published to the relay are not removed by a local wipe.
4. **Offer a way to remove a bot member from a channel** when no local record
exists — otherwise this state is unrecoverable through the UI.
5. **Warn on duplicate display names** when a member is added to a channel. Cheap,
and it would have surfaced all of this immediately.
Fix 1 is the root cause; fix 5 is the cheap guard that makes the whole class
visible.
Environment: Buzz Desktop v0.5.3, macOS, buzz.xyz hosted community.
Happy to provide the full `managed-agents.json` (redacted) and member dumps.
Contributor guide
Assessment
This issue has not been assessed yet.