Give your agent a memory of its own

A hands-on ENGRAM walkthrough · August 8, 2026

An assistant using your token remembers into your memory. Give it its own identity and you get two memories that share deliberately instead of one that blurs — plus the three things an agent gets wrong that a person never has to think about.

1. Why this tutorial exists

An assistant connected to ENGRAM with your access token remembers things into your memory. That is fine for a while. Then it starts filing its own working notes — half-finished findings, environment quirks, "the build needs --no-cache on this machine" — alongside the decisions you meant to keep, and your memory stops being yours.

Giving the agent its own identity fixes that, and buys something better: two memories that share deliberately instead of one that blurs. The agent accumulates what it learns, you keep what you decided, and anything crossing between them is an explicit act you can see and revoke.

There is also a practical reason to do this carefully. An agent writing to memory faces three questions a person never encounters, and each fails quietly — the write succeeds, returns an id, and the memory is simply never seen again:

  1. Whose memory am I writing to?
  2. Which owner ring does this belong in?
  3. Did the round trip actually work?

This tutorial answers all three, in the order they bite.

Background: Memory §3 — Memory for Agents.
Prior tutorials: Tutorial 2 (sub-agents and PATs), Tutorial 4 (a harness and its team). This one stands alone, but assumes you know what an MCP server entry is.

2. What you'll build

you  (human)                        your memory — decisions, preferences, articles
└── your-agent   (agent identity)   its own memory — findings, conventions, environment
        │
        └── one deliberate share, agent → you

Two identities, two memories, one explicit grant between them.

3. Prerequisites

RequirementNotes
ENGRAM v1.14.0+earlier builds accept a mis-scoped memory silently instead of rejecting it — you would hit Part 3's trap without the error that explains it
Admin or AgentManager roleto create the agent identity and issue its token
An MCP clientClaude Desktop, Claude Code, or any MCP host
Sharing enabledfor Part 5 only

Part 1 — Give the agent an identity

In Administration → Users → Agents, create the agent. Give it a name you will recognise in a memory list months from now — code-prod, research-assistant — not agent1.

Then issue it a personal access token. The raw key is shown once; copy it straight into the agent's configuration.

Finally, add a second MCP server entry in your client, pointing at the same ENGRAM instance but carrying the agent's token. You now have two entries that look identical apart from the credential — and that credential is the whole difference.

Identity is per connection. ENGRAM pins it server-side from the token. There is no parameter that overrides it — which means choosing the server chooses whose memory you write to, and also that an agent can never impersonate you by asking nicely.

Verify before you write

Do not assume the new entry is the agent. Ask it something own-scoped:

list_projects()

Through the agent's entry this returns the agent's own inventory — empty, on a new identity. Through yours it returns your projects. If you see your work through what you believe is the agent's connection, the token is not the one you think it is, and every memory it writes will land in your store.

Part 2 — Prove the loop before you trust it

The most valuable thing you can do on a new connection is prove the round trip once. It costs one extra call and catches every failure in this tutorial while they are cheap to fix, rather than a session later when the memory is needed and missing.

remember(
    content="On this project the integration suite must run against production-mirror; "
            "staging masks the timing bug we spent a week on.",
    owner_scope="user",
)

recall(query="which environment should the integration suite run against?")

You are looking for one specific thing in the result: via: "own".

viameaning
ownyour own memory — what you just wrote
shareda teammate granted it to you
publicshared knowledge in the instance

If the memory you just wrote does not come back as own, it is not missing — it is unreachable, which is Part 3.

Part 3 — The ring you have to choose

Every memory sits in an owner ring: how widely its author can reach it later. The rings nest — task ⊂ context ⊂ project ⊂ user.

A narrower ring is not more private. It is more situational: a context-scoped memory is recallable only while you are working in that same context.

RingRecallableUse it for
useranywhere you workdurable knowledge you want in a later session
projectwhile you declare that projecta finding that belongs to one piece of work
contextwhile you declare that conversation or sessionworking notes tied to one session
taskwhile you declare that taskscratch for a single unit of work

Here is the part that surprises people. An agent's long-term memory defaults to context, not user. That is deliberate — many agent instances run at once, and their scratch should not all pile into one shared ring. But it means a bare remember is session-local by default, which is rarely what you want from an agent you are teaching.

Try it and watch the guard fire:

remember(content="anything")

# → 400: cannot imprint a 'context'-scoped memory without context_id …
#        Written without one it would be unreachable by every caller including you.
#        Either pass the anchor, or pass owner_scope='user' for knowledge you want
#        to recall anywhere.

That error exists because the failure it replaces was silent. A context-scoped memory with no context has no context for anyone to declare — including its author — so it was written, reported as saved, and never seen again. ENGRAM now refuses rather than storing something unreachable.

So say what you mean:

remember(content="...", owner_scope="user")        # recall in any future session
remember(content="...", context_id="<session>")    # bound to this session
Rule of thumb. If you would be annoyed to lose it when the session ends, it is user.

Part 4 — What is actually worth remembering

An agent with memory tends to over-record. The useful test: would this otherwise be re-derived?

Worth keeping — a decision and why, a constraint that shaped the work, a measurement that overturned an assumption, a problem and its resolution.

Not worth keeping — anything recomputable from the code or git history, ephemeral state, unconfirmed speculation, and anything already saved as an article (articles generate their own memories; remembering their contents again just duplicates them).

Two habits that pay off later:

Long-form reference material belongs in the Knowledge Base as an article. Memory is for the atomic facts you want retrieval to surface.

Part 5 — Hand something back

The agent has its own memory now, which makes passing something to you a deliberate act:

# as the agent
share_memory(selector_kind="memory", selector_id="<memory id>",
             grantee="you@example.com", bound_scope="user")

Recall it from your own identity and it arrives with via: "shared", attributed to the agent. It stays the agent's memory — sharing passes recall, not authorship — and you can revoke it at any time from Memory Explorer → Sharing.

For anything long-form, prefer an article: the agent writes it to the KB and the article's own memory becomes recallable to whoever can see it. That keeps reference material in one place instead of scattering it across memories.

6. What this gives you

Does: a memory per identity, so neither pollutes the other · attribution that survives sharing · deliberate, revocable hand-off · an agent whose knowledge persists across sessions.

Doesn't: make the agent's memory readable by you automatically. That is the point — crossing between identities is always an explicit grant.

Appendix — Gotchas, ranked by how much time they'll cost you

  1. Verify the identity before the first write. A wrong token means every memory lands in the wrong store, and it is tedious to unpick afterwards.
  2. An agent's default ring is context. Pass owner_scope="user" for anything you want in a later session.
  3. via: "own" is the check that matters. A write that returns an id has not proved it is reachable.
  4. Don't duplicate articles into memories. Articles imprint their own.
  5. One fact per memory, written to read cold.
  6. Grantee identity is a user_id or email, never a display name.
  7. The raw token is shown once. If it is lost, rotate rather than hunt for it.