Snapshot import has no update path: reimport duplicates, and the team it created cannot be deleted
Summary
Importing a .team.json snapshot is a one-way operation. There is no way to
update an imported team in place, and no practical way to remove one, so any
change to the source of a snapshot leaves the operator stuck between duplicates
and a manual 27-step cleanup.
Two behaviours combine into the dead end:
-
Import always mints new agents. confirmAgentSnapshotImport is
documented as importing "as a brand-new agent with fresh keys", and snapshots
deliberately strip every lineage field (persona_id, persona_source_version,
source_team, source_team_persona_slug). Nothing on the wire identifies two
snapshots as versions of the same agent, so reimport can only duplicate.
-
Delete refuses while members exist. delete_team_with_cascade cascades
personas that came from a source_dir, but a JSON-imported team has none, so
agents_referencing_team is non-empty and the delete hard-fails.
Steps to reproduce
- Author a
buzz-team-snapshot v1 file with 27 members.
- Import it in Desktop. 27 agents are created and joined to a new team.
- Change one member's system prompt at the source and reimport.
→ 54 agents. No prompt was updated.
- Try to delete the team to start clean.
Cannot delete team "5ff0eeb8-07c6-4c45-9ba6-4cbf57fbbc89": 27 agent(s) still
reference it (Blender Addon Engineer, Economy Designer, Game Audio Engineer,
... 24 more). Delete or reconfigure them first.
The only supported path is deleting 27 agents individually in the UI. There is
no bulk delete, and no buzz agents delete in the CLI. Editing
managed-agents.json by hand would orphan the relay-side kind:30175 persona
heads that delete_team_with_cascade documents as needing NIP-09 tombstones.
Impact
This scales with team size, and team snapshots exist precisely to make large
teams importable in one step. A 27-agent team is 27 manual deletions per
iteration. It also makes snapshots unusable as a distribution format for any
library that changes over time, since consumers can receive a v1 but never a
v2.
Proposed fixes
Three, listed smallest first. They are independent.
1. cascade_members on team delete. An explicit opt-in flag on the delete
command that removes referencing agents and enqueues their tombstones, reusing
the cascade path that already exists for source_dir personas. Keeps the
current refusal as the default. This alone unblocks the reimport workflow.
2. Bulk delete in the UI, and a buzz agents delete subcommand. Precedent:
#2976 asks for buzz repos delete
for the same reason.
3. Optional sourceId on the snapshot, enabling idempotent import. A
stable, caller-supplied identifier that survives export. On import, a matching
sourceId offers update-in-place (definition and profile only, preserving keys,
memory, and channel membership) instead of minting a duplicate. This is the root
fix; 1 and 2 are workarounds for its absence.
sourceId is deliberately not a lineage field of the kind the format already
excludes on privacy grounds: it identifies the source artifact, not the
exporting machine, relay, or account, and it is opt-in per snapshot. Adding it
to v1 as an optional field is backward compatible in both directions, but it is
a wire-format change and worth agreeing on before anyone writes it.
Related
- #2973 — stale duplicate agents that cannot be archived or removed. Same removal gap, reached from a different direction.
- #2648 — duplicate agent identities from a second Desktop install.
- #1725 — orphaned duplicate agent definitions.
Environment
- Buzz Desktop (macOS), packaged build
- Snapshots authored externally as
buzz-team-snapshot v1
Offer
Happy to open a PR for (1), which looks self-contained in
desktop/src-tauri/src/managed_agents/teams.rs plus the command wrapper and a
confirmation in the delete dialog. Would rather agree the shape of (3) here
before touching the format.
Snapshot import has no update path: reimport duplicates, and the team it created cannot be deleted
Summary
Importing a
.team.jsonsnapshot is a one-way operation. There is no way toupdate an imported team in place, and no practical way to remove one, so any
change to the source of a snapshot leaves the operator stuck between duplicates
and a manual 27-step cleanup.
Two behaviours combine into the dead end:
Import always mints new agents.
confirmAgentSnapshotImportisdocumented as importing "as a brand-new agent with fresh keys", and snapshots
deliberately strip every lineage field (
persona_id,persona_source_version,source_team,source_team_persona_slug). Nothing on the wire identifies twosnapshots as versions of the same agent, so reimport can only duplicate.
Delete refuses while members exist.
delete_team_with_cascadecascadespersonas that came from a
source_dir, but a JSON-imported team has none, soagents_referencing_teamis non-empty and the delete hard-fails.Steps to reproduce
buzz-team-snapshot v1file with 27 members.→ 54 agents. No prompt was updated.
The only supported path is deleting 27 agents individually in the UI. There is
no bulk delete, and no
buzz agents deletein the CLI. Editingmanaged-agents.jsonby hand would orphan the relay-side kind:30175 personaheads that
delete_team_with_cascadedocuments as needing NIP-09 tombstones.Impact
This scales with team size, and team snapshots exist precisely to make large
teams importable in one step. A 27-agent team is 27 manual deletions per
iteration. It also makes snapshots unusable as a distribution format for any
library that changes over time, since consumers can receive a v1 but never a
v2.
Proposed fixes
Three, listed smallest first. They are independent.
1.
cascade_memberson team delete. An explicit opt-in flag on the deletecommand that removes referencing agents and enqueues their tombstones, reusing
the cascade path that already exists for
source_dirpersonas. Keeps thecurrent refusal as the default. This alone unblocks the reimport workflow.
2. Bulk delete in the UI, and a
buzz agents deletesubcommand. Precedent:#2976 asks for
buzz repos deletefor the same reason.
3. Optional
sourceIdon the snapshot, enabling idempotent import. Astable, caller-supplied identifier that survives export. On import, a matching
sourceIdoffers update-in-place (definition and profile only, preserving keys,memory, and channel membership) instead of minting a duplicate. This is the root
fix; 1 and 2 are workarounds for its absence.
sourceIdis deliberately not a lineage field of the kind the format alreadyexcludes on privacy grounds: it identifies the source artifact, not the
exporting machine, relay, or account, and it is opt-in per snapshot. Adding it
to v1 as an optional field is backward compatible in both directions, but it is
a wire-format change and worth agreeing on before anyone writes it.
Related
Environment
buzz-team-snapshot v1Offer
Happy to open a PR for (1), which looks self-contained in
desktop/src-tauri/src/managed_agents/teams.rsplus the command wrapper and aconfirmation in the delete dialog. Would rather agree the shape of (3) here
before touching the format.