Scoping and sharing memory
When several agents share one Postgres store, each memory needs an answer to one question: who may read it? Meaning Memory answers it with scope groups.
- A memory with no scope group is private to the agent that wrote it.
- A memory written into a group, such as
team:accounts, is visible to every agent that is a member of that group. - An access policy says which groups each agent may use. Agents can only write into groups the policy allows, and they become members of those groups.
- Removing an agent from a group does not take back what it could already see. It keeps reading what was shared while it was a member, and for an
all_historygroup that includes everything shared before it joined. See Removing an agent before you design groups for sensitive material.
For a worked example, see a support team with triage, billing and escalations agents sharing case history.
On the file backend each workspace belongs to one agent, so there is nothing to share and this page does not apply.
Write the access policy
Section titled “Write the access policy”The policy is a YAML file. This one has two agents that share a team:accounts group:
version: 1agents: support-bot: allowed_scope_groups: [agent:support-bot, team:accounts] account-mgr: allowed_scope_groups: [agent:account-mgr, team:accounts]groups: agent:support-bot: { backfill_policy: forward_only } agent:account-mgr: { backfill_policy: forward_only } team:accounts: { backfill_policy: all_history }- Group names are a prefix and a name:
team:,role:,org:orproject:, then lowercase letters, digits,-or_. A write naming a group without a prefix, such assupport, is refused. agent:<name>is each agent’s private group. Every agent needs its own, and it is never shared.backfill_policydecides what a new member sees:all_history: everything ever shared into the group, including memories written before the agent joined.forward_only: only memories shared after the agent joined.
Point each agent’s MCP server at the file with MM_SCOPE_AUTH_CONFIG, as in the Quickstart.
Create the groups in the database
Section titled “Create the groups in the database”The policy says who may share. The database records who is a member, and when they joined. meaning-memory-admin group sync makes the database match the policy. Preview it first:
MM_BACKEND=postgres MM_POSTGRES_DSN="$MM_POSTGRES_DSN" \ meaning-memory-admin --config /srv/scope_auth.yaml group sync --dry-runWould group declared: team:accounts (shares past memories) [tenant default]Would member added: account-mgr → team:accounts (and its past memories) [tenant default]Would member added: support-bot → team:accounts (and its past memories) [tenant default]3 would change.Then run it without --dry-run:
group declared: team:accounts (shares past memories) [tenant default]member added: account-mgr → team:accounts (and its past memories) [tenant default]member added: support-bot → team:accounts (and its past memories) [tenant default]3 changed.Running it again changes nothing:
In sync: the database already matches the access policy.Until you run it, no memory is shared: agents see only what they wrote themselves.
Share a memory
Section titled “Share a memory”An agent shares a memory by writing it into a group with scope_groups. Without scope_groups, it stays private:
mm_remember({"source": "agent", "text": "Zephyr Logistics asked for a discount on the March renewal; I said I'd check with the account manager."})mm_remember({"source": "agent", "text": "Zephyr Logistics renews its support contract every March.", "scope_groups": ["team:accounts"]})A group the policy does not allow is refused when the agent writes:
mm_remember({"source": "agent", "text": "Zephyr deal notes for ops.", "scope_groups": ["team:ops"]})**Error:** Validation failed: scope_groups_authz_failed: agent 'support-bot' cannot write into groups ['team:ops'] per AuthContext config (allowed: ['agent:support-bot', 'team:accounts'])Shared memories reach other agents after the next consolidation moves them into the store. On Postgres, set MM_BACKEND=postgres and the access policy on the consolidation command:
MM_BACKEND=postgres MM_POSTGRES_DSN="$MM_POSTGRES_DSN" MM_SCOPE_AUTH_CONFIG=/srv/scope_auth.yaml \ meaning-memory consolidate --agent-id support-bot --drain-only \ --workspace /srv/support-bot-mm --config-dir /srv/support-bot-mmConsolidation checks every queued memory against the same access policy before storing it, so point MM_SCOPE_AUTH_CONFIG at the file the MCP server uses. A memory written into a group the agent may not use is moved to the workspace’s .mm-journal/quarantine/ folder with the reason, and the rest are stored as usual. Consolidation re-reads the file on every run, so a policy change applies from the next run. If the policy is missing or can’t be read, the run fails and every queued memory stays queued until it can.
Afterwards, account-mgr finds the shared memory and not the private one:
mm_search({"query": "Zephyr"})**Meaning Memory** — account-mgr | 1 entries | fingerprint: `139c465af527`
| # | mem_id | Sig | Eligible | Category | Date | Text ||---|--------|-----|----------|----------|------|------|| 1 | `5e220350a7a76f3f` | 0.80 | - | fact | 2026-10-03 | Zephyr Logistics renews its support contract every March. |support-bot finds both.
Tools that take a memory id
Section titled “Tools that take a memory id”These tools apply the same rule: for a memory the agent cannot see, the answer is “not found”, so they never confirm that someone else’s private memory exists.
mm_search,mm_provenance,mm_rejections,mm_explain_visibilitymm_feedbackandfeedback_mark,feedback_promote,feedback_decay,feedback_correctmm_divergences,mm_divergence_dismiss
The other tools that take a memory id do not check visibility yet: the commitment tools (mm_close_commitment, mm_satisfy_commitment and the rest), the governance tools (mm_get_governance, mm_tag_pii and the rest), mm_queue_status, mm_grant_residency, and the relationship tools (mm_traverse_relationships, mm_explore_relationships, mm_explain_path). Given another agent’s memory id, they can return its details. An agent normally learns memory ids only from results it is allowed to see, but don’t rely on these tools to keep a memory’s existence private.
Changing the policy
Section titled “Changing the policy”After you edit the policy:
- Run
group syncagain. It adds new memberships and closes the ones the policy no longer grants. - Restart each agent’s MCP server. The server reads the policy when it starts, and uses it to check which groups the agent may write into.
Removing an agent from a group
Section titled “Removing an agent from a group”Memberships are dated. A memory shared into a group is visible to every agent whose membership covers the moment it was written. When an agent is removed from a group:
- It stops seeing memories shared into the group after the removal.
- It keeps seeing memories shared while it was a member. For an
all_historygroup, its membership counts from the start, so that includes everything shared before it joined. - If it is added back to an
all_historygroup, it also sees what was shared while it was out. Re-adding it to aforward_onlygroup shows only what is shared from then on.
Removal is not a revoke: nothing it could read before is taken away. To keep a memory from an agent for good, share it into a forward_only group that agent is not a member of, or into a group it will never be added to.
Example: a support team
Section titled “Example: a support team”A support department runs three agents. All of them need the customer and case history; only billing and escalations should see payment details; each keeps working notes to itself.
version: 1agents: triage-bot: allowed_scope_groups: [agent:triage-bot, team:support] billing-bot: allowed_scope_groups: [agent:billing-bot, team:support, role:billing] escalations-bot: allowed_scope_groups: [agent:escalations-bot, team:support, role:billing]groups: agent:triage-bot: { backfill_policy: forward_only } agent:billing-bot: { backfill_policy: forward_only } agent:escalations-bot: { backfill_policy: forward_only } team:support: { backfill_policy: all_history } role:billing: { backfill_policy: forward_only }team:support uses all_history, so an agent added to the team later reads the full case history. role:billing uses forward_only, so a new member sees payment details only from the day it joins.
group declared: role:billing (shares new memories only) [tenant default]group declared: team:support (shares past memories) [tenant default]member added: billing-bot → role:billing (from now on) [tenant default]member added: escalations-bot → role:billing (from now on) [tenant default]member added: billing-bot → team:support (and its past memories) [tenant default]member added: escalations-bot → team:support (and its past memories) [tenant default]member added: triage-bot → team:support (and its past memories) [tenant default]7 changed.Then the agents write:
| Written by | Memory | Shared into |
|---|---|---|
| triage-bot | Case 4411: Zephyr Logistics says invoices bounce since their billing address changed. | team:support |
| billing-bot | Zephyr Logistics: refund for the two bounced invoices approved; card on file expires 11/26. | role:billing |
| billing-bot | Zephyr Logistics asked twice about a discount; not raised with the account team yet. | private |
After consolidation, each agent’s search for “Zephyr” returns:
| Agent | Case note | Refund and card | Discount note |
|---|---|---|---|
| triage-bot | yes | no | no |
| billing-bot | yes | yes | yes (its own) |
| escalations-bot | yes | yes | no |
If escalations-bot is later taken out of both groups, it stops seeing new case notes and payment details from that moment, but it can still read case 4411, the refund note, and every other case note written before the removal, including those from before it joined team:support. Plan offboarding with that in mind: to cut an agent off from past cases, stop running it; a policy change alone won’t.
Several tenants
Section titled “Several tenants”A policy can hold several tenants, each with its own agents and groups. Tenants never see each other’s memories:
version: 1tenants: acme: agents: support-bot: allowed_scope_groups: [agent:support-bot, team:accounts] groups: agent:support-bot: { backfill_policy: forward_only } team:accounts: { backfill_policy: all_history } globex: agents: support-bot: allowed_scope_groups: [agent:support-bot] groups: agent:support-bot: { backfill_policy: forward_only }group sync handles every tenant in the file; --tenant acme limits it to one.