Skip to main content
← All use cases

The scenario

A support bot serves thousands of customers. Giving each their own space is operationally miserable; giving them all one space without separation means Alice’s renewal date can surface in Bob’s conversation. You want one space and a hard partition inside it.

Step 1 — Every write carries the customer

Step 2 — Every read carries the asker

Alice’s session sees Alice. Bob asking about renewal dates gets nothing, however the question is phrased — a scoped search is strict: it returns neither another user’s memories nor memories stored with no scope at all.

Step 3 — reason is scoped identically

A synthesis for Bob is built only from Bob. This matters more than the retrieve case: a summary silently blended from two customers is much harder to spot than a stray row.

Evals

  1. Write for two users. Read as each. Assert neither sees the other — in your test suite, not by eye.
  2. Write one memory with no user_id, then read as a user. It must not appear; that strictness is the guarantee.
  3. Ask reason as one user a question only the other’s memories answer. It should decline rather than blend.

Guardrails

Scoping is relevance, not access control. Anyone holding your API key can read any scope. It stops a customer’s data reaching another customer through your agent; it does not stop a caller who already has your key. For a boundary against another organisation, share the space with a role instead.
  • Adopt scoping on day one. Memories written before you started passing user_id carry no scope and are invisible to every scoped read afterwards.
  • user_id is your identifier for them. Never take it from something the end user controls, or one customer can read another’s memories by claiming to be them.

The script

Complete and runnable: support_bot_scoping.py. Next: Everything you know about one user.