Quick path
In this article
Quick read: what changed, why it matters, and what to do next.
The demo went well, which is how this kind of thing starts.
Late yesterday the agent ran clean. It opened the SaaS portal, logged in, filed the test ticket, and closed. Everyone nodded. This morning someone runs it again to show a colleague, and the portal comes up already logged in. No login screen, no credential prompt, just the dashboard, ready. It feels like progress. The friction is gone.
Then the quiet question lands. Logged in as who? The demo account from yesterday, or the admin login somebody used to fix a permissions bug at 4pm? Pointed at the sandbox tenant, or production? And whatever state just came back, is it about to be saved again on top of itself the moment this run finishes?
Nobody in the room knows. The session restored. That is all anyone can actually say.
What v0.31 actually changed
The reason this scene is suddenly common is that restoring browser state stopped being a thing you hand-rolled. It became a feature with a flag.
agent-browser is Vercel Labs' browser automation CLI for AI agents, a native Rust tool that opens pages, takes accessibility snapshots with refs, clicks and fills by ref, and reads back text. It is Apache-2.0, and it has moved fast: created in January and sitting north of 37,000 GitHub stars by the end of June. On June 25 it shipped v0.31.0, and the headline was a restore workflow.
The pull request that landed it is titled, plainly, "Harden agent session lifecycle." Read it as a list of new operating concepts, because that is what it is:
--sessionis now the stable identity for a run, withagent-browser session idandsession infoto ask which session you are actually in.--restorereopens saved browser state, and it is idempotent, so calling it twice does not double-apply.- Restore validation lets you assert the restored page is the one you expected before the agent proceeds.
--restore-saveand safe transactional auto-save persist state at the end of a run, with a deliberate refusal to overwrite good state after a failed restore or a failed validation.--namespaceisolates daemon sockets and restore-state directories, and session IDs are scoped to the git worktree.
The config schema names the same machinery in fields you can commit to a repo: session, restore, restoreSave, restoreCheckUrl, restoreCheckText, restoreCheckFn, and namespace. The schema describes restore as an auto-save and restore persistence key, and namespace as the thing that keeps daemon sockets and restore-state directories from colliding. A day later, v0.31.1 fixed an unrelated but telling bug: on Next.js 16.3 with Turbopack, the renderer id was hardcoded to 1, which could read an empty accessibility tree. State that looks present and is actually empty is a theme worth holding onto.
Strip the flags and the change is small to describe and large to live with. A browser agent can now reopen with cookies intact, reuse a running daemon, and save its own state without you babysitting a state file. That is genuinely convenient. It is also why the morning question exists. The tool made saved login state a default, and saved login state is the thing your real portals are protected by.
"Restored" answers the wrong question
Here is the trap. A successful restore proves the bytes came back. It does not prove they are the right bytes.
When the portal comes up logged in, four separate facts got bundled into one green checkmark, and the checkmark only confirms the first one:
- It opened. Cookies and storage loaded, the daemon was reused or relaunched, the page rendered. This is what "restored" means, and it is all it means.
- As whom. The session carries an account. Restore does not ask whether it is the account this workflow is supposed to use, or the one a human borrowed mid-debug.
- Against what. The same saved state can point at a sandbox or at production depending on a base URL nobody re-read this morning.
- In which namespace. With
--namespaceisolating sockets and state directories, two workflows can each "restore successfully" and be operating in different worlds. Restore does not tell you which world you are in unless you ask.
agent-browser actually gives you the tools to ask. That is the part worth crediting. session id and session info exist to answer "which session," --namespace exists to keep runs from bleeding into each other, and restoreCheckUrl, restoreCheckText, and restoreCheckFn exist precisely so the agent can refuse to proceed on the wrong page. The features are there. What is missing, on the morning after a good demo, is the habit of running them before the agent does real work.
A restored session is not proof of readiness. It is a stateful machine that needs a morning check.
The restore-state acceptance test
So here is the artifact. Not a checklist you tick once and frame, and not a security audit. A short acceptance test you run against one workflow before its saved state is allowed to touch a real account. Each row maps to something v0.31 already exposes, written so you can fill it in for any browser agent that restores state, not just this one.

Scroll sideways to see all 3 columns.
| Test row | What it confirms | What to write down before you trust the restore |
|---|---|---|
| Workflow identity | Which run this saved state belongs to | The stable --session for this one workflow, not a shared default. Run session id and session info and confirm they match what you expect. |
| Account identity | Whose login is inside the restored state | The exact account this workflow should use, and a fast way to read it back from the page. Yesterday's debug login does not get to ride along. |
| Environment | Sandbox or production | The base URL or tenant the restored session points at, asserted, not assumed. A restore that "worked" against production is not a win if you meant the sandbox. |
| Namespace | Which isolated world the run lives in | The --namespace for this workflow, so sockets and restore-state directories cannot collide with another agent's. One namespace per blast radius. |
| Restore key | Which saved state is being loaded | The restore persistence key, named on purpose, so you know which snapshot reopened and where it lives on disk. |
| Validation | That the restored page is the right page | A restoreCheckUrl, restoreCheckText, or restoreCheckFn the agent must pass before it acts. If validation fails, the run stops instead of guessing. |
| Auto-save rule | When state gets written back | Whether --restore-save is on, and the explicit rule that auto-save must not overwrite good state after a failed restore or failed validation. Decide this before the run, not after. |
| Failure behavior | What happens when restore or validation fails | The agent halts and preserves the last known good state. Confirm a bad restore degrades to "stop and keep," never to "save the mess on top." |
| Proof of work | That the run did what it claimed, where it claimed | Evidence tied to the right session and environment: a final snapshot or read-back, not just an exit code. "Completed" should mean observed on the right page. |
| Reset | How fast you get back to a clean slate | The one move that clears or rotates the saved state and forces a fresh login: which key to delete, which namespace to wipe, who can do it under pressure. |
The two rows that catch people are Environment and Auto-save rule.
Environment, because saved cookies do not announce which tenant they belong to, and the difference between sandbox and production is one base URL that nobody re-reads when the page comes up already logged in. Auto-save, because the convenient default is to persist state at the end of every run, and that is exactly how a half-finished or wrong-account session gets written back as the new "good" state and quietly restored tomorrow.
This is a cousin of the permission lease I have written about before, and it is not the same artifact. A lease scopes what an agent is allowed to touch before it ever drives. This test runs later, on a narrower question: given that the agent is allowed to drive and now reopens with state already loaded, is that state the right state to act on. Same instinct, different gate.
Why this is now an operations primitive
What changed is not that browser agents got more powerful. It is that their memory got durable, and durable memory is an operational thing, not a convenience thing.
A stateless agent fails honestly. Point it at a portal and it hits a login wall, and the wall is a checkpoint. A human decides, every single run, which account and which environment. Persistent restore removes that checkpoint by design. That is the whole point of the feature, and it is a good feature. It also means the decision that used to happen at the login screen now has to happen somewhere else, on purpose, or it does not happen at all.
The agent-browser team clearly saw this coming. The v0.31 work reads less like "add restore" and more like "make restore safe to operate": restore you can rerun without corrupting state, validation hooks that let the agent refuse the wrong page, auto-save that will not write over good state after a failure, and compatibility checks that decide whether a session gets reused, relaunched, or restarted instead of letting requested flags fall silently on the floor. Those are the moves of people who expect this to run unattended and want the failure modes to be boring.
The same lesson keeps showing up from a different door. A separate browser profile matters because identity bleeds when you do not draw the line. Localhost stops being a sandbox the moment an agent can browse to it. And now restored state stops being a convenience the moment it can put the wrong account in front of a real portal without anyone choosing it. The pattern underneath all three is the same: a boundary you never wrote down is the one that surprises you. The AI workflow controls worth having are the ones that turn that boundary into a step, not a memory.
None of this is a knock on agent-browser. It is a fast, well-built tool that just made a hard thing easy, and the team did the unglamorous safety work to go with it. The point is narrower and lands on you: the morning check is yours to run. The tool can refuse the wrong page only if you tell it which page is right.
Your next move
Take the one workflow you would actually restore first. The real one, on a real portal, the thing that made the demo feel solved yesterday. Fill the ten rows above for that single workflow before its saved state touches a real account again.
You do not need all ten perfect to start. You need to know which ones are blank. The AI workflow security review worksheet covers the same ground for identity, approvals, evidence, and shutdown paths, and the AI workflow controls page shows where the test fits in a larger process.
If a row comes up empty and you want a second set of eyes, bring one browser-automation workflow and we will map the restore-state test with you before it reopens anything that matters. That is also how we scope process automation: get the restore right first, then let the agent reopen the door.
Restore-state help
Make a browser agent pass the morning check before it restores state
Bring one browser-agent workflow. BaristaLabs will help pin down session identity, namespace, the validation check, the auto-save rule, the failure behavior, and the reset path before saved state touches a real portal.
Best fit for teams testing browser agents on support portals, CMS edits, QA passes, invoice admin, or internal dashboards.
Practical AI Workflow Notes
Want more practical AI operations ideas?
Get short notes on applying AI inside real small-business workflows — from document handling and customer follow-up to internal reporting, compliance, and automation guardrails.
Turn this idea into a pilot
Which workflow should go first?
Use the readiness check to compare impact, effort, risk, owner, and next step before booking a call.
- 3-5 minutes
- Deterministic score
- No sensitive data
Share this post
