Skip to content

Persona rename leaves linked instances on the old relay identity, and the rename guard makes it unrecoverable #5705

Description

@eeSeeGee

Summary

In desktop-v0.5.10, a persona-linked agent instance can end up with a name that differs from its persona's display_name. When that happens:

  1. The Desktop UI shows the new name and the agent's system prompt uses the new name, so the rename looks successful.
  2. The relay identity (kind:0 display_name) is republished from record.name on every agent start, so the published name silently reverts to the old one.
  3. @mention resolution runs against the relay member list, so mentioning the agent by the name the UI shows fails to resolve and the message is never delivered.
  4. There is no recovery path in the app. Renaming again cannot fix it, because the propagation helper skips exactly the records that have diverged.

Observed on a real workspace: three builtin-persona agents renamed on 2026-08-10 kept publishing Fizz / Honey / Bumble two days later, while their definitions, prompts and sidebar entries all read Monkey2 / Dummy2 / Goofus2. Only a hand-edit of managed-agents.json fixed it.

Root cause

1. The rename guard makes divergence permanent

propagate_persona_name_rename only renames instances whose current name equals the persona's old display_name:

if record.name != old_display_name {
    continue; // pool-named instance — keep its individualised name
}

The intent is sound — pool-named instances (Birch, Compass) should keep their individual names. But the guard is also the only thing standing between a diverged record and repair, and the condition it tests can never become true again once record.name and persona.display_name differ for any reason. Each subsequent rename moves old_display_name further away. The record is stranded permanently.

There is no UI to edit a persona-linked instance's name directly (same limitation noted for acp_command in #5508), so the owner's only fix is editing managed-agents.json by hand with the app quit.

2. Relay-synced persona renames don't propagate at all

apply_inbound_persona overwrites local.display_name and local.system_prompt from an inbound kind:30175 event, but — unlike update_persona — never calls propagate_persona_name_rename and never touches linked instances:

local.display_name = inbound.display_name;
local.avatar_url   = inbound.avatar_url;
local.system_prompt = inbound.system_prompt;

So a rename performed on device A and synced to device B updates B's definition and prompt while B's instance keeps its old name. That is a divergence created by sync alone, with no user error involved — and by defect 1, device B can then never repair it through the UI. This looks like the same ownership problem as #5218, seen from the naming side.

3. Startup reconciliation actively overwrites any manual correction

start_managed_agent builds the reconcile payload straight from the instance record (agents.rs#L1114-L1123):

let reconcile = ProfileReconcileData {
    name: record.name.clone(),
    ...

and profile_needs_sync treats any relay name that differs from record.name as stale and republishes.

This is correct behaviour given a correct record.name, but it means a stale instance name is not merely unpublished — it is re-asserted over a correct relay profile on every single start. An owner who repairs the relay profile out-of-band (buzz users set-profile --name) sees the fix silently reverted the next time the agent boots.

Evidence from the affected workspace

managed-agents.json, desktop-v0.5.10, macOS 26.6.1. Definition rows carry pubkey: ""; instance rows carry the pubkey and persona_id.

persona_id definition display_name instance name instance display_name
builtin:fizz Monkey2 Fizz absent
builtin:honey Dummy2 Honey absent
builtin:bumble Goofus2 Bumble absent
2c586e69-… (never renamed) Mrs Altman Mrs Altman
e3c3724a-… (never renamed) PSSOXBot PSSOXBot
216103d5-… (never renamed) youngbot youngbot

The absent instance display_name is the diagnostic: propagate_persona_name_rename sets record.name and record.display_name together (update.rs#L50-L51). Neither is set on any of the three, so the helper never ran for them — consistent with the guard skipping all three.

system_prompt propagated correctly in all six cases (all three renamed agents run prompts that open "You are Monkey2 / Dummy2 / Goofus2"), which is why the rename looks complete from inside the app.

Startup republish, three for three:

agent last start relay display_name after
builtin:fizz 2026-08-12 19:04:28Z Fizz — overwrote a manual correction made 2 days earlier
builtin:bumble 2026-08-12 21:01:19Z Bumble — same
builtin:honey 2026-08-10 20:32:18Z (not restarted since) Dummy2 — manual correction survived

After hand-editing the three instance name fields with the app quit, builtin:fizz restarted at 2026-08-12 21:28:37Z and the relay profile stayed Monkey2.

Reproduction

Direct repro of defect 1 (no sync required):

  1. Create an agent from a persona, then make record.name differ from persona.display_name by any route — hand-edit, sync, or pool naming.
  2. Rename the persona in Desktop.
  3. The sidebar and system prompt update; record.name does not.
  4. Start the agent. The relay kind:0 display_name is republished with the old name.
  5. Rename again to try to fix it. It still does not propagate — the guard now compares against an even older name.

Repro of defect 2: rename a persona on device A, let the kind:30175 event reach device B, inspect B's managed-agents.json — the definition is renamed, the instance is not.

Likely origin in this case (hypothesis)

The owner migrated to a new laptop and imported their previous setup. A plausible chain that matches every timestamp on disk: the fresh install seeded builtin instances with the code defaults (Fizz / Honey / Bumble, definitions created 16:25:13Z, instances 16:35:15Z), an imported/synced definition then set the persona names to the values from the old machine, and the owner's UI rename ~4 hours later (20:29Z) compared record.name = "Fizz" against an old_display_name that was no longer Fizz — so the guard skipped it.

I could not confirm which write path ran on 08-10; that state is gone. The two code-level defects above stand on their own regardless of how the initial divergence was introduced.

Suggested direction

Not prescribing the ownership model — #5328 and #5508 are already circling it — but three things would each have prevented this independently:

  • Distinguish "pool-named" from "diverged" explicitly rather than inferring it from name equality. If instances recorded whether their name was individualised (pool-drawn/user-set) or inherited from the definition, the guard would be a flag check and inherited names would always follow a rename.
  • Give apply_inbound_persona the same propagation as update_persona, so a synced rename cannot create the divergence in the first place.
  • Surface the divergence. An agent whose published relay identity differs from the name shown in the UI is user-visible breakage — mentions to it fail — and should not be silent. A stale-name badge, or an editable instance name for persona-linked agents, would give owners a recovery path that is not "quit the app and edit JSON".

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