← 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
- Write for two users. Read as each. Assert neither sees the other — in your
test suite, not by eye.
- Write one memory with no
user_id, then read as a user. It must not
appear; that strictness is the guarantee.
- 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.