Share a memory with someone¶
A memory share is a per-user grant: you hand one named person reader or
writer access to your own memory, without adding them to a team and
without changing who owns it.
It's the narrowest of Hadron's access mechanisms. If you want a group with
symmetric access, you want team membership
on a group-class memory instead; if you want a whole organization to read
something, you want a knowledge memory and org membership.
What can be shared¶
Only personal-class memories. That's the whole rule, and it's worth
internalising because the failure mode is opaque (see
Troubleshooting).
| Class | Shareable? | Use instead |
|---|---|---|
personal |
Yes | — |
private |
No — owner-only, by design | Nothing; privacy is the point. |
knowledge |
No | Org membership, or a cross-org subscription. |
group |
No | hadron memory member — symmetric team access. |
app, system |
No | App/Agent scoping. |
Who you're allowed to share with¶
There's a second rule on top of the class, and it depends on whether the memory belongs to an org:
- An org-owned personal memory can be shared only with a current member
of that org. Naming an outsider fails with
CrossOrgShareNotAllowedError. - A free-standing (org-less) personal memory — one created with
--owner-me— can be shared with anyone. - Agent-scoped personal memories are exempt from the org-membership restriction above — their audience is governed by App membership and the user's Agent subscription rather than by org membership. Shares still apply; in fact this is the pattern shares were built for (see below).
Shares are how per-pairing isolation works
On an Agent-scoped personal memory, the share is the mechanism: Alice's memory paired with Mentor A is a different memory from the one paired with Mentor B, each with its own share. So don't read the exemption above as "shares don't apply here" — it only means the grantee doesn't have to be an org member; App membership and the Agent subscription govern instead.
Before you start¶
- You must be the memory's principal — its owner. Only the principal can grant, change, or revoke a share on it. There's no admin override.
- You need a way to name the grantee. Any of these work:
The server resolves the reference against the full user table, so sharing a free-standing memory by email or handle works even when you have nothing else about the person.
1. Grant access¶
Two roles, and the difference is exactly what it sounds like:
| Role | Can |
|---|---|
reader |
Read every node in the memory. |
writer |
Read, and create, edit, and delete nodes. |
Neither confers ownership. A share never lets the grantee re-share the memory, delete it, or manage its other shares — those stay with the principal.
create upserts: naming someone who already has a share updates their
role instead of failing, so it's safe to re-run.
2. See who has access¶
Each row shows the grantee, the role, and when it was granted. The grantor
is always the principal — even when an App backend made the call on their
behalf, in which case the acting party is recorded separately in createdBy.
3. Change a role¶
Re-running create with a different role does the same thing; set-role just
says what you mean.
4. Revoke, or leave¶
The principal removes someone else's access by naming them:
A grantee removes their own access by omitting --grantee — the
"stop sharing this with me" path:
Two things to know about revocation:
- It takes effect on the next read. There's no deactivated state — the row is deleted — so an in-flight request may still complete.
- Revoking as the principal is idempotent: removing a share that's already
gone succeeds. Leaving is not — the share row is your authorization, so
a second leave answers
FORBIDDEN(you already left).
A grantee can leave a memory even after its owner has soft-deleted it, so a share can't strand you.
Troubleshooting: FORBIDDEN is deliberately vague¶
If you're not the principal, every failure looks the same. FORBIDDEN does
not distinguish between:
- the memory doesn't exist,
- the memory isn't
personal-class, or - you aren't its principal.
That's intentional — collapsing them stops the API being used to probe which
memories exist. The same uniformity covers the grantee reference: a
non-principal gets FORBIDDEN whether or not the named user exists, so users
can't be enumerated either.
So if a share fails and you are the owner, check the class first — a
private or knowledge memory will refuse a share and tell you nothing more.
As the principal you will get a distinct NOT_FOUND when the grantee
reference resolves to nobody, which is the one case that's safe to report.
Other named failures: CrossOrgShareNotAllowedError (the grantee isn't a
member of the org that owns the memory) and MemoryShareGranteeMissingError
(the reference didn't resolve to a user).
Other surfaces¶
- GraphQL —
createMemoryShare/deleteMemoryShare/ the share list, withgranteeReftaking the same id / email / handle / URN forms. (The oldergranteeIdargument is deprecated in favour ofgranteeRef.) See the GraphQL API reference. - Portal — you can see memories shared with you, and leave one, from the memories list. Granting a share is not in the portal yet, so use the CLI or GraphQL for that.
- MCP — no share tools yet.
Related¶
- hadron CLI reference —
memory membervsmemory share, and the full command surface. - Memory access — how the different grants compose.
- Memory ownership and lifecycle — what "principal" means per class.
- Debug PERMISSION_DENIED errors — when a grantee still can't read something.