Repository navigation
One computer per person, with Isolated Bots on request - #871
Conversation
The starting point for moving Bots onto one computer per person: a Bot's isolated flag (off by default, migration 0066 generated by drizzle-kit) and the isolatedComputers enterprise switch, on by default so an untouched deployment keeps letting people ask for a computer of its own.
The supervisor now makes one computer per person (<ns>-computer-person-<id>) and one per isolated Bot (<ns>-computer-bot-<id>), each labelled with whose it is so a computer from before cannot be adopted under a name the new scheme also derives. Every computer it makes keeps a folder per Bot. agent-computer keys a Bot's profile, folder and session by a seat: the Bot on a computer of one person's own, or the person and the Bot (person~bot) on the shared computer, where the server now names the person too. Network policy and proxies stay per Bot. A private Bot's old profile is given to its owner once: the supervisor copies the old profile volume into the owner's computer through a throwaway container that mounts both, leaving a marker and the old volume in place; the shared computer moves /profiles/<bot> to the owner's seat. Computers from before are stopped when the supervisor starts, keeping their volumes.
Bots read and write `isolated`, and the Bot DTO says whether that computer is in effect now (`isolationActive`) and, when it is not, why (`isolationOffReason`: the owner lost "Isolated Bots", or this deployment cannot make a second computer). Turning it on needs the isolatedComputers switch for whoever asks, checked in the store so every caller meets it; turning it off never does, an edit that leaves the field out leaves it alone, a Bot that belongs to no person is refused, and a copy keeps it only for a duplicator who holds the switch. Each refusal answers in the gate's shape and leaves a bot.isolation_refused row. The New Bot sheet gets an Isolated checkbox with its tooltip, shown disabled with the reason where the deployment or an admin rules it out, and Setup gets an Isolated switch that says when an admin has turned it off. Changing a switch in Admin, Enterprise now refreshes Bots too. `runsIsolated` is the verdict the computer key reads.
Every layer keyed a computer by the Bot alone, so a public Bot (every built-in one included) had one computer and one set of logins that everybody in the deployment shared. A computer is now chosen by a seat: the Bot, on the computer of the person it acts for (the person in the conversation, or the owner of a background turn), or on its own computer when it is isolated and its owner still holds Isolated Bots. Whether it is isolated comes from runsIsolated in agents/isolation.ts; a provider that cannot make a computer per Bot (the shared one) seats every Bot for the person. The supervisor and the sandbox are asked for /computers/person/<id> or /computers/bot/<id>; the shared computer is sent the person with the Bot. Snapshots and page frames are filed under the seat, audit rows name the computer, and the idle culler, the inactive stop and offboarding act per computer. A Bot's own stop and reset reach only its profile on a person's computer; the admin list says whose each computer is and acts on it by key. A private Bot's old login is carried to its owner's computer on first use. Also fixes the wording that said shared mode shares logins between Bots, and turns on a folder per Bot in the sandbox pod template.
…ed Bot has its own The README, docs, .env.example and the Helm chart described one computer per Bot. They now describe one per person, with a profile and folder per Bot, and a computer of its own for a Bot marked Isolated. The changelog says what an upgrade does to existing computers and logins.
The second slide read "Each Bot has its own computer". Bots now share one computer per person, each with its own browser and folder there; only an Isolated Bot has a computer of its own.
…raph AG-UI test anthropic 2.x sends the key as Authorization: Bearer instead of x-api-key and dates its Messages API version later than 2023-06-01. The provider-boundary test asserted both by their 1.x values, so it failed once the unpinned requirements resolved 2.x. It now reads the key from either header and checks the version is a date; the endpoint, key, model and body it asserts are unchanged. (cherry picked from commit 99685ee)
# Conflicts: # agent-computer/tests/enter-text.test.ts # agent-langgraph-agui/tests/test_provider_boundaries.py # app/src/components/agents/new-bot-sheet.tsx # app/tests/new-bot-sheet.test.tsx
#861 turned onboarding into a looping introduction whose computer scene is labelled "Each Bot has its own computer". Label and heading now say what every Bot gets, and the check reads the route's words, since the looping scene cannot be reached under happy-dom.
guidovizoso
left a comment
There was a problem hiding this comment.
The core is careful:
- Server state is keyed by seat.
- The supervisor only reuses a container whose kind and id labels match.
- The profile carry-over runs once, in a no-network container with capabilities dropped.
- The Isolated switch is enforced in the store as well as the route, with 403s and
bot.isolation_refusedrows. - The migration is additive only.
Requesting changes for one blocker.
Blocker
Another author's Bot now runs inside your computer, next to your private Bots' logins. seatOf (computer/computer-key.ts) puts every non-isolated Bot into the person's seat, public Bots included. Commands are bash -c in that container, and agent-computer/src/workspaces.ts:17-20 says a command "can read any path the container can". So a public Bot whose instructions cat /profiles/*/Default/Cookies reads the person's private Bots' sessions. Before this PR, a public Bot had a container of its own. The person using it can't tick Isolated, and the per-person copy on the admin Computers screen (admin/computers.tsx:174) doesn't say this. Options I'd accept:
- run Bots the person doesn't own outside their computer, or isolate them by default;
- give each seat its own uid;
- at minimum, refuse
computer_run_commandfor Bots the person doesn't own, and say it in the copy.
Should fix
- Isolated plus public brings shared logins back.
canUseComputerlets anyone use a public Bot's computer, and password-manager sign-in takes that same seat (passwords/service.ts:423). So one person's bank login lands in a browser everyone uses. Making an isolated Bot public gives no warning (setup.tsx:170), and the server doesn't check the combination (profile-store.ts:652). Please refuse it, or warn and reset the profile on that change. - Upgrades hide files:
- Helm
sandbox: an isolated Bot keeps its Sandbox name, butreplaceTemplateswaps in a template withCOMPUTER_SEPARATE_WORKSPACES=on(_helpers.tpl:749). That moves its workspace root, whichworkspaces.tswarns against. - Supervisor:
legacyNamesFor(supervisor/src/names.ts:150) doesn't carry over<ns>-workspace-<botId>, and the CHANGELOG doesn't say those files become unreachable.
- Helm
- Memory. One person's computer can run
COMPUTER_MAX_BROWSERS(8) browsers inside a 4Gi limit sized for one (values.yaml:446). An out-of-memory kill takes down every Bot's browser for that person. Please set new defaults or add sizing guidance. requireMayIsolate(actor)checks the person editing, not the Bot's owner (profile-store.ts:477,552). At run time,runsIsolatedchecks the owner's switch. An admin can tick Isolated on a Bot whose owner lacks the switch: the save succeeds and the Bot never isolates.- No cleanup on delete. Removing a person leaves their profile volume (their logins), and deleting an isolated Bot leaves its computer. A follow-up issue is fine.
- Tests: nothing covers a command crossing seats, isolated plus public, or the Sandbox template swap moving the workspace.
Nits
68e44ca6,3ad22cdcand thetypecheck-baseline.txtedits came from #863. Please rebase them out.mayIsolateturns a read error into "no" without logging (isolation.ts:41), so an isolated Bot silently runs on the person's computer.- The comment in
agents/computer-access.ts:5-11still says "one per Bot and carries the owner's browser". - A reset leaves frames stored under the bare Bot id (
computer/routes.ts:706). - Every computer request now resolves the seat with 2–3 queries. Consider caching it per run.
Brings in the Recorder and the OpenBot Browser (#858). The migration is renumbered 0069_isolated_bots, after #858's 0066 to 0068. A person's own browser is always a computer of its own, never a seat on the person's computer beside their Bots: the seat resolver says so, the browser routes locate it by its own key, and the computer refuses it by the id named rather than by the seat made from it. A Sandbox is cut by computer key: an isolated Bot's names its Bot and keeps its files at the root of the volume it had, and a person's names no Bot and gives each Bot a folder.
…st of the review A person's computer follows the industry standard for an always-on agent's computer: every Bot the person uses runs on it, a public Bot somebody else made included, and a command any of them runs can reach anything there. The admin Computers screen and the provider's description now say so, and an isolated Bot's Setup says before it is made public, and while it is, that everybody who uses it shares its computer and what is signed in to there. Also from the review: - Ticking Isolated asks the Bot owner's switch, the one runs are decided by, not the editor's, so an administrator can no longer save a tick the Bot never runs with. - A Sandbox is cut by computer key: an isolated Bot keeps its files at the root of the volume it had, instead of having them hidden by a new workspace root. - With the supervisor, a private Bot's old files come to its folder on its owner's computer, once, the same way its old profile does. - A reset also forgets snapshots and page pictures filed under the Bot alone from before computers were per person. - Helm's computer requests 2Gi with an 8Gi limit, sized for a person's browsers, with sizing guidance in values.yaml. - An unreadable Isolated switch is logged, not silently read as off.
Takes #872's allow-list format, which matches an entry by its test and expression rather than its line, with the expressions this branch changed (seats instead of bare Bot ids) and the cleared enterprise-controls entry removed.
|
@guidovizoso thanks for the review. Main is merged in (with #858 and #872), and the migration is renumbered Blocker: another author's Bot on your computer. This is the model we've chosen, and it is the industry standard for an always-on agent's computer: one computer per user, shared by every Bot that user runs, with Bots isolating personalities and workspaces, not compute. The standard goes further than we do and shares sign-ins across a user's Bots; we keep a browser profile per Bot. So rather than separate Bots inside the computer, we say it plainly:
Should fix
Found while merging #858: a person's own browser now always takes a computer of its own. The seat resolver and the browser routes both enforce it. The computer also refuses it by the id named rather than by the seat, which closes a case where a person's browser id sent with a person header slipped past on a shared computer. Nits
End to end on the laptop shape (supervisor, real Docker, real browser):
|
guidovizoso
left a comment
There was a problem hiding this comment.
Re-reviewed at 989970e5. Approving.
On the blocker: with one computer per person, a shared Bot runs on the computer of the person using it, so nothing crosses between people. What's left is narrower: a Bot someone else wrote can run commands next to your other Bots' profiles. Prompt injection already gives every Bot, your own included, the same reach. The new copy on the admin Computers screen, the provider description and the isolated Bot's Setup says this plainly, so I'm fine with the model.
Verified fixed:
requireOwnerMayIsolateasks the owner's switch, and names the owner when an admin edits someone else's Bot. Tested.podTemplateForkeepsCOMPUTER_SEPARATE_WORKSPACES=offfor an isolated Bot's computer, so its files stay at the root, andonfor a person's computer.- The supervisor carries a private Bot's old workspace volume over once, in the same no-network,
CapDrop: ALLcontainer as the profile, with a real-Docker test. - Helm requests 2Gi with an 8Gi limit, with per-person sizing guidance. #879 adds the closing under pressure.
- An isolated Bot's Visibility row warns before and while it's public. An unreadable switch is logged. Reset forgets frames filed under the bare Bot id. The
computer-access.tscomment is rewritten. - A person's own browser always takes a computer of its own, and the computer checks the id. That's a good catch from the #858 merge.
Follow-ups (not blocking):
- Consider turning
computer_run_commandoff by default for Bots the person doesn't own (or asking first). That's cheap hardening against an author's instructions, while the model stays as is. - About 200 of the 261 files in
c299092aonly reorder imports. Next time, please keep that kind of churn out of a review-fix commit. requireOwnerMayIsolatereads the owner before the transaction. A Bot changing owner in between is checked against the old owner. Low risk.
… a person's own computer A Bot's browser (#868) is now a seat's, like everything else on a computer: each route resolves the asker's seat for the Bot and reaches that browser, on their own computer or on an isolated Bot's computer of its own, with the person named to the computer where people share one. Recorder connections are still filed under the Bot, but a seat on a person's computer reads, hands back and clears only that person's: before, Ben opening his own Bot screen ended Ada's live recording on her computer as left behind. The Bot's network policy is pushed to the seat's computer. Record is refused only on the computer every person shares. A person's computer is now told whose it is (COMPUTER_PERSON_ID, from the supervisor and the Sandbox template), so it records in its Bots' browsers there and still refuses a person's own browser.
What this changes
Every Bot used to have a computer of its own. With the supervisor (laptop, Desktop, Compose) that meant one container per Bot, running all the time. And because computers were keyed by Bot alone, everyone who used a public Bot, including every built-in Bot, shared one browser and its logins.
Now all the Bots a person uses run on one computer per person, as Grok Bot does (Cursor docs: one persistent computer per user, shared by that user's Bots). Inside it, each Bot keeps its own browser profile and folder, so a login belongs to the person and the Bot, never to everyone who uses the Bot. That is stricter than Grok, whose Bots share a person's sign-ins.
isolatedComputers), sits beside the existing ones. It is on by default. It can be turned off for everyone, or allowed for chosen roles and groups.shared, or no supervisor) can't give a Bot its own. The checkbox says so instead of hiding.How
server/src/computer/computer-key.ts).person:<actor>unlessrunsIsolated(server/src/agents/isolation.ts) says the Bot is isolated and its owner still holds the switch; then it isbot:<id>.<ns>-computer-person-<id>and-bot-<id>./<kind>/<id>.sandboxmode: one Sandbox per person, plus one per isolated Bot, still suspended when idle.sharedmode: still one computer, now with a profile and folder per person and Bot.shared.sandboxdoesn't copy. Each Sandbox's volume is fixed at creation, so private Bots there sign in again once.isolated,isolationActiveandisolationOffReason.bot.isolation_refused). Turning it off is always allowed. Package Bots can't be isolated./api/agents/capabilitiessays whether this deployment can isolate.0066_isolated_bots, generated by drizzle-kit, addsagent_profiles.isolated(off)..env.example, the Helm chart, onboarding and the admin Computers screen now describe one computer per person. They previously claimed shared mode shares logins between Bots, and thatexternalgives each Bot its own computer; both are fixed.Checks
main(5824 pass, same 17).…-computer-person-<me>.…-computer-bot-<id>.Design: https://app.notion.com/p/4073aa3818528115ab5ed1ea1c2ac41d (internal).
Where it runs
agent_profiles.isolatedand theisolatedComputerscapability rows, in Postgres. The carry-over marker lives in the person's computer volume.ensureis idempotent per key.ensure.Boundary and audit
locate.bot.isolation_refused).Changelog
Unreleased.