Scoping
Every write and every read carries a scope. It is four fields, and only the first is required.
| field | required | meaning |
|---|---|---|
user_id | yes | who the memory belongs to. One store per user. |
agent_id | no | which agent produced or should see it |
run_id | no | which run / conversation it belongs to |
project_id | no | which repository or workspace it belongs to |
Source: Scope in server/models.py.
The store boundary is the user
user_id is not a filter — it selects the store. Per-user stores are separate SQLite databases, which is why one process must own them (see Self-hosting) and why a cross-user query is not a thing you can accidentally write.
The other three fields are narrowing, applied within one user's store.
Narrowing, not partitioning
This is the part that surprises people, and it is deliberate.
A memory written with a project_id still surfaces when you read without one. A memory written without a project_id surfaces inside every project.
told SodaMem outside any project ──▶ visible everywhere
told SodaMem inside repo A ──▶ visible in repo A, and when you drop the keySo dropping the project_id from a query answers "how did I fix this in the other repo?", which is the question that makes cross-project memory worth having. If you want hard partitioning, use different user_ids — that is the boundary that actually isolates.
How coding assistants set it
sodamem install derives project_id from the git root. A git worktree resolves to its parent repository, so one branch per task is not one memory bank per task — which is what you want, since the task and its branch share the same context.
Override with --project-id, or opt out entirely with --no-project. See CLI · install.
Scope is bound at construction, never at inference
In the agent-framework adapters, scope is fixed when you construct the tools and never appears in the schema the model sees.
A user_id the model can choose is a user_id it can hallucinate. Keeping it out of the tool schema is the difference between a model that cannot read another user's memory and a model that merely usually doesn't.

