The problem
A personal AI assistant is only useful if it remembers you, works in the background, and acts across your tools. Giving every user their own server does not scale. Putting every user on one server risks the worst bug an assistant can have: one person's memory showing up in another person's answer.
The assistants also need to work together, and sometimes with agents that belong to other companies. Every one of those hand-offs is a new place for data to leak or for instructions to be injected.
Architecture
One runtime serves every user. Each turn arrives through a channel, passes an identity router, and runs in an agent loop that loads only that user's stores. Turn state lives in Postgres, so the runtime itself holds nothing between turns.
Key decisions
The tenant comes from identity, never from the model
Every store and every tool reads the tenant from the verified sign-in. No tool accepts a user or tenant id as model input, so a prompt cannot talk the agent into another user's data. Isolation tests plant a deliberate leak and expect every store to fail.
Delegation through a task ledger
A lead assistant hands work to role assistants: one for the inbox, one for research, one for scheduling. Each hand-off is one database row that is at once the queue item, the link to the parent task, and the result. The role assistant works under its own identity. The lead waits on the row without spending model calls, delegation stays one level deep, and a stuck task times out.
Other companies' agents over A2A, on a short leash
Partner agents are added by an operator, and their address and key are pinned at that moment. The system never trusts an address that a partner advertises later. Outbound calls are HTTPS only, cannot reach private networks (checked again after DNS lookup), and have timeouts and size caps. Every send needs a person to tap allow, and every reply comes back marked as untrusted text from another company.
Memory is data, not instructions
Long-term memory is ranked by meaning, keywords, importance, and recency. A filter refuses any memory that tries to give the assistant orders, so a poisoned note cannot become a standing instruction.
Turns that survive a crash
Turn state is written to Postgres as the turn runs. If a process dies, another one resumes the turn. Bursts of messages from one chat merge into one turn, so a fast typist does not start five parallel answers.
Thin clients on a contract that only grows
The web and desktop apps hold no records of their own. They speak a small HTTP contract that may only add fields. A breaking change gets a new route, and both sides keep a contract test.
Results
- Adding a user adds rows, not servers.
- Isolation is enforced by identity and proven by tests, not by convention.
- Assistants delegate to each other and to outside agents, and nothing leaves without a person's approval.
- A crashed process resumes its turns instead of dropping them.
Tradeoffs
One level of delegation cannot express deep plans, but it keeps cost and loops bounded and every task traceable. A shared runtime means one noisy user can affect others, so turns are rate-limited per conversation. Partners are added by hand, which is slower than an open directory and much safer.