Skip to content

Multi-tenant Phase 1: tenant context + guest agent + per-user memory - #13

Merged
ssethia2 merged 1 commit into
mainfrom
ss/multi-tenant-phase1
Jun 16, 2026
Merged

Multi-tenant Phase 1: tenant context + guest agent + per-user memory#13
ssethia2 merged 1 commit into
mainfrom
ss/multi-tenant-phase1

Conversation

@ssethia2

Copy link
Copy Markdown
Owner

Foundation for the friends-trial (the "personalization, no email/calendar" scope) — and the first slice of SaaS multi-tenancy. Lets one Aria serve isolated guests without exposing the owner's data.

What's here

  • tenant.py — a contextvars current-user seam. Owner runs with no context (everything unchanged); a guest is set per-request.
  • memory.py — when a guest is set: add_memory/search_memory route to that guest's own ChromaDB collection (mem_<user>), and load_profile() returns {}. Owner path is byte-for-byte identical (scratchpad + aria_memory + profile.json).
  • agent_core.pybuild_tools(guest=True) returns an account-free subset (memory + weather + web only — no email/calendar/contacts/notes/reminders/music/home/browser/system). build_agent(guest=True) builds it; the system prompt gets a GUEST MODE banner + empty profile/standing-rules.

Safety

  • Guests can't see your data or each other's — different collection per user, empty profile, restricted tools.
  • Owner path untouchedis_guest() is False with no context; 45 tools; 212 tests pass.
  • Invoke the guest agent only with a tenant context set (documented on build_agent/tenant.py); Phase 2 (webvoice) enforces this.

9 new tests prove the routing/isolation (real vectors need network, so routing is mocked).

🤖 Generated with Claude Code

…isolation

The foundation for letting friends try Aria without seeing the owner's data.

- tenant.py: a contextvars-based current-user seam. Owner = no context (unchanged);
  a guest is set per-request, routing memory/profile/toolset to that user.
- memory.py: when a guest is set, add_memory/search_memory hit that guest's OWN ChromaDB
  collection (mem_<user>) and load_profile() returns {}. Owner path byte-for-byte the same
  (scratchpad + aria_memory collection + profile.json).
- agent_core.py: build_tools(guest=True) returns an account-free subset (add_memory,
  search_memory, get_weather, web_search, fetch_webpage) — no email/calendar/contacts/
  notes/reminders/music/home/browser/system. build_agent(guest=True) builds it; the system
  prompt gets a GUEST MODE banner and empty profile/standing-rules.

Isolation proven with tests (routing mocked since real vectors need network): guest add/
search hit mem_<user>; owner uses the scratchpad; guest toolset excludes account tools;
guest profile is empty. 212 tests pass; owner path unchanged.

Next: Phase 2 wires this into webvoice (per-friend tokens → user_id → guest agent).

Assisted-by: Claude Code (Opus 4.8)
@ssethia2
ssethia2 merged commit 200b254 into main Jun 16, 2026
1 check passed
@ssethia2
ssethia2 deleted the ss/multi-tenant-phase1 branch June 16, 2026 03:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant