Share a memory with someone¶
Let exactly one person in, and take it back whenever you want. A memory
share hands one named colleague reader or writer access to a memory of
yours — without adding them to a team, without making it org-wide, and without
changing who owns it. Nobody else gains anything.
You can do all of it in the portal. Open a personal-class memory you
own and pick its Sharing tab: it lists who currently has access, and lets
you grant a person, change their role, or revoke them. That is the whole task,
with nothing installed — the numbered steps further down are the same four
operations from the hadron CLI, for when you want to script them. (The tab
appears only for someone who may see the share list, so on a memory that is
not yours you will not find 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 — the full owner's half: the memory's Sharing tab lists who has access and lets you grant, change a role, and revoke (portal#839, closing #668). Separately, you can see memories shared with you, and leave one, from the memories list.
- 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.