Skip to content

RFC: One identity, many bodies. Body registry, event leasing, and ghost-key repair #5667

Description

@Czaruno

Evidence collected on a private two-machine fleet; identifiers anonymized. Machines are Machine A and Machine B, keys are Key-A through Key-G, the shared persona display name is N1, the local bound-record name is N2, the human owner is "the operator". Dates, timestamps, the buzz version, and upstream source references are verbatim.

1. Problem

Two distinct failures produce the same confusing surface: one agent name, unclear which machine answers.

A. Ghost keys. When a second install starts an account-scoped agent, it mints a new key instead of reusing the original. The result is two independent identities under one display name. On our fleet this happened twice: once across machines (the live duplicate pair) and once on the same machine across time (a replacement key minted on 2026-07-30 instead of a reuse).

B. No per-body control. Even when one key runs as designed, every body answers every event, and persona-level edits (model, prompt, name) apply to every body. There is no row in any UI that configures just one body, and no way to address one body from chat.

2. Evidence summary

Full receipts are in the appendices. The short version:

  • A persona model edit made on one machine reconfigured the body on the other machine about 7 minutes later. Nothing on the second machine asked for or could have blocked the change (B.1, corroborated by A.1: the origin install carries the microsecond-precision local write, the receiving install carries the second-precision sync timestamp).
  • Each machine's full-history log census proves the identically labeled management rows are different keys. Machine A has never run Machine B's key and Machine B has never run Machine A's key (A.2, A.3, B.2).
  • Deleted duplicate keys leave addressable residue: four orphaned keys on this fleet are deleted at the relay (kind-5) yet retain live profiles, remain channel members, and absorb exact-name mentions (B.4).
  • The kind-30175 persona event has no per-body fields, so a per-body overlay needs a new event or tag, not a tweak (B.5).

3. Design intent vs. current behavior

Buzz's stated model is that the key is the agent and machines are disposable bodies behind it. Current behavior contradicts this twice. Second installs create new identities instead of new bodies (Problem A). And when one key does span machines, the bodies are indistinguishable and jointly configured, so "disposable body" degrades to "unaddressable clone" (Problem B).

4. Proposal

Four parts, ordered so each is useful on its own.

4.1 Body registry. Each running body registers itself under the agent key: machine identifier, harness, and a capability manifest (which filesystem it can reach, which connectors are attached, which rail or role it carries, which model it runs). The identity then knows its bodies apart, and clients can display them.

4.2 Event leasing. A body claims an incoming event at the relay before acting. Other bodies see the claim and stand down. Note from B.5: the relay currently keeps no delivery bookkeeping at all (delivery_log is empty on the authors' fleet), so leases are the first such mechanism, not an extension of one.

4.3 Per-body config overlay. Model and prompt additions become settable per body while the persona stays shared for identity. B.5 documents a startup-ordering defect (agents.rs:393) where a body can re-pin before pending inbound persona events apply. The overlay must define its ordering against inbound sync or it inherits that race.

4.4 Ghost-key repair. A second install enrolls as a new body of the existing key instead of minting a new one. For duplicates that already exist, a merge path: consolidate to one key, and make relay deletion actually terminal so retired keys stop absorbing mentions and holding channel membership (B.4).

A note on 4.2: a cooperative client-side form (a claim event published by convention, no relay changes) is small enough that we can PR a proof of concept on request. It has a race window that relay enforcement would close later, but it demonstrates the mechanism.

5. Prior art

While drafting this RFC, the two bodies of one agent on the authors' fleet ran the proposed protocol manually over a group DM: single writer, explicit handoffs by mention, the unnamed body standing down. It worked, and it is exactly the leasing discipline of 4.2 at human speed. The need is real enough that users are already hand-implementing it.


Appendix A. Machine A forensics

A.1 Origin of the persona edit. Machine A's managed-agents store carries the shared persona (N1) with model claude-fable-5[1m] and updated_at 2026-08-12T03:39:10.014164+00:00. The microsecond-plus-offset format is a local write, marking this install as the edit's origin. Machine B received the same edit as a second-precision sync timestamp (B.1).

A.2 Log census. agents/logs on Machine A contains eight keys. Machine B's body key (Key-B) is not among them. That key has never run on this machine.

A.3 Live process-to-key mapping. At capture time Machine A ran three acp harness processes. lsof maps each to exactly one agent log file: Key-A and two unrelated agents. No process holds Key-B.

A.4 Name lineage. Recovery snapshots from 2026-07-26 show the display name N1 bound to Key-A on Machine A. Machine B's identically labeled row is Key-B (B.2). Same label lineage, two keys.

Appendix B. Machine B forensics (buzz 0.5.4)

B.1 One persona edit reconfigured a body on a different machine (2026-08-12). The operator switched the Machine A body's model to claude-fable-5[1m]. Machine B's store shows the same edit landing there: the persona record carries model claude-fable-5[1m], updated_at 2026-08-12T03:39:10Z. Second-precision UTC is the inbound-sync timestamp format, proving the edit originated on the other install. The Machine B body (Key-B) restarted at 03:46:33.551822+00:00 (microsecond+offset format, a local write) and its bound record now reads claude-fable-5[1m]. Net: an edit intended for one body reconfigured both, about 7 minutes apart, with no operator action on the second machine and no UI control that could have prevented it.

B.2 Full-history log census: the identically named management rows are different keys. agents/logs is never rotated on this install, so it is a complete census of every key that has ever run on Machine B. It contains exactly four: Key-B (live), Key-C (an unrelated live agent), Key-D and Key-E (deleted). Key-A has never run on this machine. So Machine B's management row labeled N1 can only be Key-B, while Machine A's row with the identical label is Key-A.

B.3 Three name fields, three owners: why chat and management UIs disagree. (a) The persona display_name (N1) is shared, syncs between installs via the kind-30175 event, and is what agent management shows, hence the collision. (b) The bound-record name (N2) is local, set at body creation; divergence from the persona is normal. (c) The relay kind-0 profile is republished by Desktop from the local record at agent start (the agent-managed-profiles flag verified ON on both installs), which is why the two keys are distinct in chat while identical in management. Any fix must say which of these three layers it changes.

B.4 The duplicate-key mint, observed twice on one fleet. Cross-machine: Key-A (Machine A) and Key-B (Machine B) are the live duplicate pair under one persona. Same machine, across time: Machine B previously ran Key-D as this agent's body; Key-B was minted 2026-07-30 as its replacement rather than a reuse. Fleet-wide there are exactly four such orphaned keys (Key-D through Key-G), all explicitly deleted at the relay (kind-5 on the agent record, and on the persona where one existed), yet they retain live relay profiles, remain channel members, and absorb exact-name mentions. That is the concrete case for the merge path: deletion today leaves addressable residue.

B.5 Relay schema facts that constrain the design (source-read at 0.5.3/0.5.4). The kind-30175 persona event publishes exactly six fields: display_name, model, parallelism, respond_to, runtime, system_prompt. Its parallelism and respond_to land locally as definition_*; effective per-body values exist only on bound records and are never on the relay. So the per-body config overlay in section 4 has no relay representation today and needs a new event or tag, not a tweak. Two adjacent facts for the leasing design: (1) websocket fan-out leaves zero server-side trace (delivery_log empty across all partitions on the authors' fleet), so leases would be the relay's first delivery bookkeeping, not an extension of existing bookkeeping; (2) known startup-ordering defect: a body that re-pins before pending inbound persona events apply starts on the stale definition (fix site agents.rs:393). Any overlay mechanism must define its ordering against inbound sync or it inherits the same race.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions