Can we actually run multiple browser agents in parallel without
I've been digging into the architecture of SessionDock—a local Linux environment for Chromium workspaces—and it tackles this by treating the browser not just as a profile, but as a managed resource.
The problem with simple profile separation
Using a separate --user-data-dir in Chromium keeps your logins apart, but it doesn't track ownership. In a complex deployment, you need to know exactly which project a workspace belongs to and who is authorized to move the mouse or type at any given millisecond.
A directory structure can't tell you if an agent is still allowed to execute a click that was queued three seconds ago but only just arrived at the browser instance.
Managing slots and bindings
In the SessionDock model, a "slot" is more than a folder. Each slot gets its own:
- Complete Chromium user-data directory
- Dedicated download directory
- Separate XDG and D-Bus paths
- A private Weston desktop for graphical isolation
Crucially, the scheduler binds these slots to specific metadata: the project, the worktree, and the expected tenant. This prevents an agent from accidentally jumping between different environments on every request. It’s a strict binding; the agent doesn't just "pick" a profile, it is granted permission for a specific binding.
Using leases and epochs to prevent collisions
To stop a person and an agent from writing to the same slot simultaneously, you need an exclusive, time-limited access right—a lease. But the real secret to a clean handover is the "epoch."
An epoch is a monotonically increasing generation number. Every time control changes hands (e.g., from Agent to Human), the epoch increments. When an action reaches the browser, the system checks the epoch attached to that action. If the current epoch is 42 but the action arrives with epoch 41, the system drops it because that authorization has expired.
Here is a conceptual look at how that logic handles a handover:
1. Agent A is granted a lease for the slot at epoch 41.
2. The human user interrupts and takes control back.
3. The scheduler increments the current epoch to 42.
4. A delayed "click" command from Agent A arrives, tagged with epoch 41.
5. The system compares 41 < 42 and rejects the action to prevent state corruption.Real-world constraints
This isn't a magic plug-and-play tool yet. There are some clear gaps in the current implementation. For example, while the data model tracks "expected accounts," it doesn't actually verify if the website is signed in. It's a record of intent, not a verified state. Similarly, the worktree assignment is currently just a conceptual link in the core; it doesn't automatically discover Git worktrees or open the correct URLs.
For anyone building a custom LLM agent that needs to survive in a browser, focusing on this "lease and epoch" pattern is way more reliable than just spinning up five different Chrome profiles and hoping for the best.