Skip to content

Memory ownership and lifecycle

Reference and target — not all of this is shipped yet

This page describes the target state for memory ownership and the soft-delete lifecycle. Pieces are already in place — Memory.deletedAt / deletedBy columns exist, the basic deleteMemory resolver is live — but the parent-cascade rules, the reference-block checks, and the cross-org block-list checks land alongside the user-installing-app spec (#43). Treat this page as the design contract the implementation is converging on.

TL;DR — the mental model

Hadron has two relevant ideas:

  • An Agent is a blueprint. It's authored once, owned by an organization, and declares what memories it expects, what surfaces it can run on, who can install it.
  • An App is a house built from that blueprint. Installing an Agent produces an App. The App runs in some org, has members and credentials, and accumulates operational data.

You never run an Agent. You install an Agent, and then you run the App that the install produced.

This blueprint/house distinction is what makes ownership unambiguous. Memories you'd casually call "the Agent's memory" actually divide along this line — the Agent owns the conversation design; the App owns everything that accumulates from running it.

Memory roles and their owners

Every memory has a class (a stored field on the Memory row) and, when it lives inside an App, a URN role marker that names its slot in the URN tree. Class describes content type. Role marker describes URN position. They're related but not the same.

Memory class URN role marker (inside an App) Owner Why
system systemhrn:memory:org::app::agent::system Agent The conversation design. One per Agent. Survives every install.
app app-memhrn:memory:org::app::app-mem App Shared operational data across all callers of this install.
group group-mem:<group-slug>hrn:memory:org::app::agent::group-mem:<g> App A team's shared memory inside an install. The URN names the Agent for slug uniqueness; ownership flows up to the App.
app (per-user) app-user:<user-slug>hrn:memory:org::app::agent::app-user:<u> App Per-user operational data for App-keyed sessions. Isolated across installs of the same Agent.
personal priv:<user-slug>hrn:memory:org::app::agent::priv:<u> App (URN) / User (semantically) The user is the strict-ownership boundary for read/write (see Memory access); the URN ownership still keys on the App so multi-install isolation holds.
knowledge n/a — hrn:memory:org::<memory-slug> (no App segment) Organization Reference content the org publishes; agents reference it via AgentMemoryItem.

Two things the table is easy to read past:

  • URN-attached ≠ owned. group-mem, app-user, and priv all name an Agent in their URN (for slug uniqueness across multiple Agents inside the same App), but they're owned by the App. When the App is deleted, they cascade with the App — not with the Agent.
  • Agents own exactly one memory: their system memory. Everything else an Agent appears to "have" is either App-owned (memories that live inside an install) or referenced (knowledge memories the Agent attaches via AgentMemoryItem).

For who can read or write each class, see Memory access. The rest of this page is about who owns the memory — i.e., what happens when that owner is deleted.

Deletion is parent-cascade

In Hadron's MVP, you never directly delete a memory owned by an Agent or an App. You delete the parent, and the parent's memories soft-delete with it. There are three deletion pivots.

Pivot 1 — deleting an Agent

When you soft-delete an Agent:

  • ✅ Its system memory is soft-deleted with it.
  • ✅ All its AgentMemoryItem rows (the join table linking the Agent to attached knowledge memories) are hard-deleted. The knowledge memories they referenced are untouched — those keep living in their owning org.
  • group-mem, app-user, priv memories are not cascaded here. Those exist only when an App has installed this Agent — and if any App has installed it, you can't delete the Agent in the first place (see below).

Block-list — cross-org. An Agent cannot be soft-deleted while any live AppAgent row (an App that has installed it) or AgentImport row (another Agent that has imported it as a dep) references it. The rule applies across organizations — an App in another org keeps your Agent alive until that org soft-deletes their App or removes the import.

In practical terms: the foreign-org admin coordinates the unblock by uninstalling on their side. Once their AppAgent is soft-deleted, your Agent becomes deletable. A soft-deleted reference counts as "absent" for this check — you don't have to wait for hard-delete.

AgentMemoryItem rows do not block. Agents that just use knowledge memories don't constrain the memory owner; only declarations that embed the Agent (AppAgent, AgentImport) do.

Pivot 2 — deleting an App

When you soft-delete an App:

  • ✅ All four App-owned memory roles cascade: app-mem, group-mem, app-user, priv.
  • ❌ The Agent the App was built from is not deleted. The blueprint outlives the house. Another org may have installed the same Agent; your install going away doesn't affect them.

No foreign-ref block-list. Apps cannot be referenced by AgentImport or AgentSubscription — those entities always name an Agent directly, never an App. An App is freely deletable from its owner's side; there are no foreign refs that could block it.

Pivot 3 — deleting a standalone Memory

knowledge-class memories owned directly by an Organization (with no Agent or App in the ownership chain) can be soft-deleted via the deleteMemory mutation — unless any live AgentMemoryItem row references the memory.

If references exist, the mutation rejects with a typed error listing the blocking agents. The owner has to wait for the subscribing agents to detach the memory before the delete proceeds. There is no force-delete path in MVP.

What "soft-delete" means in MVP

  • The row stays in the database with deletedAt and deletedBy set.
  • Every read surface (myMemories, marketplace, agent attachments, blended-graph queries, the portal lists) filters the row out.
  • References from outside resolve to a typed error rather than crashing.
  • There is no recovery / undelete in MVP. Once soft-deleted, the row stays gone from user-facing surfaces. This is intentional — MVP needs misclick-resistance around big deliberate actions (Agent/App delete), not "any memory can be brought back."
  • There is no auto-purge / retention sweep in MVP. Soft-deleted rows accumulate indefinitely.

The lack of auto-purge is a known compliance gap. Pre-revenue with no EU PII at scale, it's acceptable. Before that changes, an ops-only force-hard-delete CLI will need to land. Treat that as a known follow-up, not a hidden risk.

A worked example — Bea's Mealplan

Bea owns Bea's Bakery and authors the Mealplan Agent. Acme installs Mealplan, producing the Mealplan @ Acme App. Acme's chefs add a shared shopping list (group-mem:dinner-team) and Bob's private dietary preferences (priv:bob).

Bea tries to delete Mealplan (the Agent):

  • Blocked. An AppAgent row exists for Mealplan @ Acme, referencing Mealplan. The error includes "blocked by 1 install in org Acme."
  • Bea cannot proceed until Acme soft-deletes their Mealplan @ Acme App.

Acme deletes Mealplan @ Acme (the App):

  • ✅ The App's app-mem soft-deletes.
  • ✅ The group-mem:dinner-team soft-deletes.
  • ✅ Every app-user:* and priv:* memory for this install soft-deletes.
  • ❌ Mealplan (the Agent) keeps running for other orgs.

Bea retries her Agent delete:

  • ✅ Succeeds. Mealplan's system memory soft-deletes. Its AgentMemoryItem rows hard-delete; the knowledge memories they referenced (Bea's Recipe Library) are untouched.
  • Mealplan @ Acme's AppAgent row is already soft-deleted — no longer blocking.

Bea then tries to delete her standalone Recipe Library knowledge memory:

  • If no other Agent of hers still has it attached: ✅ soft-deletes.
  • If another of her Agents (say, Catering Pro) still has an AgentMemoryItem pointing at Recipe Library: ❌ rejected with a typed error listing Catering Pro as the blocker. Bea has to detach the reference (or soft-delete Catering Pro) first.

Open questions for the implementation team

Decided in principle, not yet detailed at the implementation level:

  • Notifying foreign-org admins when their AppAgent is the sole blocker on someone else's Agent delete. MVP returns a typed error to the deletion attempt; no banner, no email. Post-MVP work.
  • The dangling-ref hazard (an unresponsive foreign org permanently blocking your Agent delete) is documented and accepted at MVP scale. A post-MVP escape valve (typed-reason force-delete with an audit row, or stale-ref threshold) is a future spec, not part of this work.
  • Subscription-style entities (AgentSubscription, MemoryShare, MemoryMember) — these may block Agent deletion or memory deletion in principle, but the exact behavior is captured separately. AgentSubscription blocking Agent deletion is explicitly out of MVP for now.

Where the rules come from

The rules above were settled in the 2026-05-15 soft-delete-memory design discussion, with four registered as cross-session decisions: D-2026-05-15-001 through -004 in the decisions registry. Implementation is gated on the user-installing-app spec (#43), which introduces the AppAgent and AgentImport entities the block-list checks depend on.

See also

  • Agents and Apps — the blueprint/house distinction explained in depth, with the PWA analogy.
  • Memory access — who can read or write each memory class (parallel to this page's who owns it).
  • Understanding memory — what memories are made of (nodes, edges, classes).
  • SubscriptionsAgentOrgGrant and AgentSubscription, the cross-org grants that interact with Agent deletion.
  • Deleting a memory — the task-oriented guide for the portal UI, walking through each of the three deletion paths.