dejo

One AI agent, three signed-in roles: customer, vendor, admin

BlogBy Rohit Kashyap

I build Dejo, and this post is about one of its features, so read it as a builder explaining a design choice. The Playwright parts are from its own docs.

A lot of real apps have more than one kind of user. A marketplace has buyers, vendors and admins. A support tool has customers and agents. To test the full flow, or just to get a job done, you need to act as one, then another, then the first again: the customer places an order, the vendor accepts it, the admin approves the payout, the customer checks the status.

With one browser and an AI agent, that turns into a lot of signing out and back in. And it brings a quieter problem: order starts to matter. If one task forgets to sign out, the next one runs as the wrong person, and you get a confusing failure two steps later.

How Playwright tests solve it

Playwright's authentication guide has a clean answer for test suites. In a setup step you sign in once per role and save each role's browser state to a file, like playwright/.auth/admin.json. Tests then load whichever file they need. For a test where an admin and a user interact, you open two browser contexts, each with its own saved state.

That works well when you write the tests as code. It's less natural for an AI agent working in one live browser through MCP.

What happens with an agent

Playwright MCP keeps one persistent profile per project folder by default, and the docs note a profile "can only be used by one browser at a time." To be someone else you start the server with a different --user-data-dir, or load a saved login file with --storage-state in isolated mode. Both mean restarting the browser tool between roles, which an agent in the middle of a task can't do on its own.

One profile per role

In Dejo, a profile is a whole signed-in browser of its own: its own cookies, its own session, its own window. You can have several, and they stay signed in side by side.

From your agent, dejo_profile("vendor") switches to the vendor profile. The first time you name a profile it's created empty, so you sign it in once with dejo_login. After that, switching is instant and nothing gets signed out. dejo_profile() with no name lists them and says which one is active, and every dejo_run result names the profile it ran as, so a log tells you who did what.

From a terminal, signing in each role looks like this:

dejo --profile customer login --site shop.example.com
dejo --profile vendor   login --site shop.example.com
dejo --profile admin    login --site shop.example.com

Each opens a window; you sign in as that person, and you're done for as long as the site keeps the session.

The site is learned once

Profiles split the sign-ins, not the memory. When the vendor's session explores the order pages, Dejo saves a map of what it saw. When the admin later works on the same site, that map is already there, so the agent doesn't start from zero. The site is one site, however many accounts reach it.

Saved routes work the same way. A route like "accept the newest order as a vendor" is saved once and replayed with one call, from whichever profile you've switched to.

Passwords per role

If a role signs in with a plain password form that you want filled on every run, the password stays outside memory, in an environment variable named after the site, the profile and the field:

DEJO_SECRET_SHOP_EXAMPLE_COM_ADMIN_PASSWORD=...
DEJO_SECRET_SHOP_EXAMPLE_COM_VENDOR_PASSWORD=...

Dejo looks for the profile's own value first and falls back to a site-wide one. If you ask it to run as admin and only a vendor password exists, it says so instead of quietly signing in as the wrong person. The full lookup order is in the sign-in docs.

Two things to plan for

Chrome allows one running browser per profile. If two agents work at the same time, give each its own profile folder (for example by starting the second one with DEJO_PROFILE set), or one of them will fail to open the browser.

And sessions still expire on the site's schedule. When one does, the run comes back needs_login, and you sign that one profile in again. The others aren't affected.

When this is worth it

If you only ever act as one user, you don't need any of this. It pays off when a flow crosses roles, when you test permissions ("can a vendor see another vendor's orders?"), or when one person runs a site from several accounts every day. The common thread is that order stops mattering: any task can run as any role, at any time, without signing anyone out.

FAQ

How do Playwright tests handle several signed-in roles?

Playwright's docs recommend signing in once per role in a setup step, saving each role's browser state to its own file (for example playwright/.auth/admin.json), and loading that file in the tests that need the role. For roles that interact in one test, each gets its own browser context.

Can Playwright MCP be signed in as two users at once?

Not in one profile. Playwright MCP keeps one persistent profile per project folder, and a profile can only be used by one browser at a time. You can point it at a different profile with --user-data-dir, or load a saved login with --storage-state in isolated mode, but switching means starting the server differently.

Does each Dejo profile learn the site separately?

No, on purpose. Profiles split the sign-ins, not the memory. What the vendor's session learned about the site's pages is there when the admin works on the same site.