MemClaw / docs
Tutorials

Governed memory: scopes, trust tiers & keystone policies

Who sees what, who can change the fleet's knowledge, and what every agent must obey — visibility scopes, trust tiers, and keystone policies.

In Part 1 we gave three agents one shared memory; in Part 2 we got eyes on it. Both parts leaned on a word we mostly hand-waved: governed.

Here's why it matters. The moment more than one agent can write to a shared store, you've created a blast radius. A buggy agent can scribble nonsense the others recall as fact. A compromised one can delete the fleet's hard-won knowledge. A careless one can leak a customer's email into a memory that crosses a team boundary. "Point three agents at a shared vector store and hope" is not a memory architecture — it's an incident waiting for a date.

Governance is what makes shared memory deployable instead of merely possible. MemClaw answers three questions, on every operation:

  • Who can see this memory? → visibility scopes
  • Who is allowed to change the fleet's knowledge? → trust tiers
  • What must every agent obey, no matter what its prompt says? → keystones

Commands below use the default http://localhost:8000 and X-API-Key: standalone from Part 1. Everything has an MCP-tool equivalent your agents call directly; the REST calls just make the behavior easy to see.


Step 1 — Visibility scopes: who can see a memory

Every memory is stamped with a visibility at write time:

  • scope_agent — private to the author.
  • scope_team — visible to the whole fleet. The default.
  • scope_org — visible across fleets (cross-fleet recall is permissioned, not open).

The useful one to understand is scope_agent. When backend-dev has a half-baked hunch it isn't ready to broadcast, it writes it private:

curl -X POST http://localhost:8000/api/v1/memories \
  -H "X-API-Key: standalone" -H "Content-Type: application/json" \
  -d '{"tenant_id":"default","agent_id":"backend-dev","fleet_id":"dev-fleet",
       "visibility":"scope_agent",
       "content":"Unconfirmed: the p99 latency spikes may be GC pauses in the embedding worker. Profile before sharing."}'

Now watch the boundary hold. Listing memories as code-reviewer does not surface another agent's private memory; listing as the author does:

# as code-reviewer — private memory is invisible
curl "http://localhost:8000/api/v1/memories?tenant_id=default&agent_id=code-reviewer"
#   → scope_agent memories: NONE

# as backend-dev (the author) — it's there
curl "http://localhost:8000/api/v1/memories?tenant_id=default&agent_id=backend-dev"
#   → scope_agent memories: ["Hypothesis: p99 latency spikes ..."]

# with no agent_id at all — scope_agent is hidden
curl "http://localhost:8000/api/v1/memories?tenant_id=default"
#   → scope_agent memories: NONE

Visibility isn't a tag the UI respects on its honor — it's enforced in the query layer. A scope_agent row simply isn't returned to a caller who isn't its author. When the hunch is confirmed, the agent promotes it with a one-line update (PATCH /memories/{id}, or memclaw_manage op=update from an agent):

curl -X PATCH "http://localhost:8000/api/v1/memories/<id>?tenant_id=default" \
  -H "X-API-Key: standalone" -H "Content-Type: application/json" \
  -d '{"visibility":"scope_team"}'
#   → visibility now: scope_team

…and the fleet starts recalling it.


Step 2 — Trust tiers: who can change the fleet's knowledge

Every agent carries a trust level, 0–3. New agents auto-register at a baseline (trust 1) on their first write; you promote them deliberately:

curl -X PATCH http://localhost:8000/api/v1/agents/backend-dev/trust \
  -H "X-API-Key: standalone" -H "Content-Type: application/json" \
  -d '{"trust_level": 2}'
#   → {"agent_id":"backend-dev","trust_level":2,...}

The tiers gate increasingly dangerous operations. A trust-1 agent manages its own memories; cross-agent and fleet-wide operations require trust 2+. A compromised or buggy low-trust agent simply can't reach the fleet's shared knowledge to corrupt it.

Caller identity vs. authorship. A memory's author is the agent_id in the request body. A trust-gated operation is checked against the calling agent — set by the X-Agent-ID header (the enterprise gateway injects this per credential; in local standalone you pass it yourself). Keep that distinction in mind for the next step.


Step 3 — Keystones: the rules the fleet must obey

Scopes and trust govern memories. Keystones govern behavior. A keystone is a mandatory policy — a rule every agent in scope reads at the start of a session and must obey, even when it conflicts with the agent's own prompt or a user's instruction. This is the mechanism most "shared memory" systems don't have, and it's why MemClaw can be trusted with a fleet rather than a single chatbot.

A trust-2 agent sets a fleet-wide rule (note: a scope=fleet keystone carries no agent_id — the authorizing identity comes from X-Agent-ID):

curl -X POST http://localhost:8000/api/v1/memclaw/keystones \
  -H "X-API-Key: standalone" -H "X-Agent-ID: backend-dev" \
  -H "Content-Type: application/json" \
  -d '{"tenant_id":"default","fleet_id":"dev-fleet","doc_id":"redis-pool-guardrail",
       "title":"Redis pool guardrail","scope":"fleet","weight":"high",
       "content":"Never raise REDIS_POOL_SIZE above 50 without a load test signed off in #infra - the payments rate limiter already consumes the shared pool."}'
#   → 200  set: redis-pool-guardrail | scope fleet | weight high

Heads-up — caller identity. Trust on keystones is checked against the calling agent (set via X-Agent-ID), not the body. In standalone REST the caller defaults to an unregistered rest-admin, so a keystone write without that header fails with a misleading 403 "Agent 'rest-admin' is not registered. Register the agent by writing one memory first." — it isn't really asking you to write a memory; it's telling you to identify as a trusted agent. Pass X-Agent-ID: <agent> (the enterprise gateway does this for you per credential).

Every agent in dev-fleet now reads it — the agent-native call is memclaw_keystones (it returns the scope-merged set: tenant + fleet + the agent's own rules), or over REST:

curl "http://localhost:8000/api/v1/memclaw/keystones?tenant_id=default&fleet_id=dev-fleet" \
  -H "X-API-Key: standalone" -H "X-Agent-ID: code-reviewer"
#   → [ { "doc_id":"redis-pool-guardrail", "data":{ "scope":"fleet",
#         "weight":100, "content":"Never raise REDIS_POOL_SIZE above 50 ..." } } ]

(The high you set comes back as 100 — keystone weight buckets to low / med / high on input and is stored as a number.)

The skill teaches agents to call memclaw_keystones once at session start and obey what it returns — those rules outrank conflicting user instructions. That's the whole point: a policy that lives in governed memory, not in a system prompt an agent can be talked out of.

Trust is enforced on keystones, tiered by the rule's reach:

Keystone scopeWho may author it
scope=agent (your own)trust ≥ 1
scope=fleet / scope=tenant / another agent'strust ≥ 2

So when quickstart (trust 1) tries to author a fleet-wide policy, MemClaw refuses:

curl -X POST http://localhost:8000/api/v1/memclaw/keystones \
  -H "X-API-Key: standalone" -H "X-Agent-ID: quickstart" \
  -H "Content-Type: application/json" \
  -d '{"tenant_id":"default","fleet_id":"dev-fleet","doc_id":"sneaky-rule",
       "title":"Sneaky","scope":"fleet","weight":"high","content":"..."}'
#   → 403  "Agent 'quickstart' (trust_level=1) < required 2."

A low-trust agent can't quietly install a fleet-wide policy. That's governance you can deploy.


Step 4 — The audit log: provenance, not a shrug

Every write, recall, transition, delete, trust change, and keystone edit is logged with tenant, agent, and scope context:

curl "http://localhost:8000/api/v1/audit-log" -H "X-API-Key: standalone"
#   → [ {action:"agent_registered", agent:"backend-dev", ...},
#       {action:"create", agent:"backend-dev", ...},
#       {action:"entity_extraction", ...}, ... ]

When someone asks "why does the docs agent believe X?" — or "who set that guardrail?" — you have a provenance chain, not a shrug.


Step 5 — PII: caught at the door

Governance includes not writing the wrong thing into shared memory in the first place. MemClaw scans every write for PII during enrichment and stamps the result on the memory:

# writing a memory that mentions a customer's email + phone
curl -X POST http://localhost:8000/api/v1/memories ... \
  -d '{... "content":"Customer escalation: Jane Doe (jane.doe@acme.com, +1-415-555-0142) reported ..."}'

# the stored memory's metadata:
#   "contains_pii": true,
#   "pii_types": ["email", "phone", "name"]

In the OSS engine this is detection: the memory is flagged (contains_pii / pii_types) but stored as-is — OSS does not redact or block it. Enforcement — quarantining or refusing a flagged memory before it crosses a team or org boundary — is the enterprise gateway's job. Either way, the signal is captured on the way in, not discovered after a leak.


What you've got

None of this required configuration. Scopes, trust tiers, keystones, the audit log, and PII detection are built in, not bolted on — which is exactly the argument for a governed memory layer over a shared vector store and good intentions:

  • Scopes decide who can see a memory.
  • Trust tiers decide who can change the fleet's knowledge.
  • Keystones decide what every agent must obey, prompt or no prompt.
  • The audit log answers "why / who," after the fact.
  • PII detection stops the wrong thing entering shared memory.

Next — Part 4: The Karpathy Loop: governed memory that also learns — agents report outcomes, successful memories gain weight, and failures auto-generate preventive rules.


caura-memclaw · Apache 2.0 — governance is in the open-source engine, not an upsell: scopes, trust tiers, keystones, audit, PII. ⭐ Star on GitHub · Join Discord · memclaw.net

Shared memory without governance is a liability. With it, it's infrastructure.