After you press Send
The anatomy of one Vera work turn, from the moment a request is accepted to the moment the result is in your hands: eight stages, the real incidents that forced us to redesign them, and what still does not work.
Abstract
An AI assistant that does work, not only answers questions, has to survive everything that can happen during a task that lasts minutes: a closed laptop, a dropped connection, a worker that dies mid-command, a web page that tries to give the model orders. We describe the architecture of Vera, the assistant built by VLabs, by following a single request through the eight stages of a work turn. The design rests on three commitments: accepted work is stored before it is acknowledged, a resent request does not create a second turn, and a turn is not reported as done without real content and a delivery receipt. We explain the mechanism behind each commitment, including a server-side ledger that makes every device a view of the same work, a browser that runs on the user’s own device so that login sessions never reach the server, a per-session sandbox that holds no credentials, and a completion protocol that requires real content and a delivery receipt. For each stage we report the production incident or internal measurement that motivated it, and we close with the limitations that remain.
Keywords: AI agents, durable execution, idempotency, on-device browser automation, prompt injection, sandboxing, delivery guarantees.
With a chatbot, pressing Send is simple. A question goes up, an answer comes down, and it is over in seconds. If the network drops halfway, you ask again.
Vera also carries out tasks. One turn can run for minutes, open a website you are signed in to, run code on your files and leave an Excel workbook behind. A lot can happen in those minutes: you close the laptop, the network flickers, a worker machine dies in the middle of a command, or a web page contains a line of text written to give orders to an AI.
Most of our engineering effort has therefore gone into what surrounds the language model. Vera is built around three commitments:
- Accepted work is stored before it is acknowledged, so it survives whichever device goes dark.
- A resent request does not create a second turn.
- A turn is not marked done until a real result exists and the app confirms it was displayed.
This article follows a single request through eight stages. At each one we describe what can go wrong, what the system does about it, and in several cases the real incident that forced us to redesign it.
Open the supplier site I’m signed in to, pull November’s price list, compare it with last month’s Excel file and flag anything that went up more than 5%. Do this again every Monday morning.
The request is short, but it needs a browser that holds your login session, a safe place to run code on the Excel file, and a weekly schedule. Those three things live in three different places.
- 1AdmissionStore the request before acknowledging itVLabs server
- 2The ledgerRecord every step; any device can read itVLabs server
- 3Context and toolsChoose what to remember, find the right toolVLabs server
- 4BrowserOpen the page with the session on your machineYour device
- 5Running codeCompare two price lists inside a sealed boxSession sandbox
- 6ProgressReport what is happening, accept new inputVLabs server
- 7FinishingProve a result exists and that you received itVLabs server
- 8Results and scheduleFiles expire; each rerun needs its own grantYour device
Stage 1VLabs server
Admission: store first, acknowledge second
The first thing the server does with your request is not a model call. It writes the request to the database, and only then tells the app “received”. The order matters. If the server acknowledged first and stored second, a failure in between would create a request the app believes it sent and the server has never heard of.
Every request carries its own key, created by the app. If the network drops at the moment of sending, the app cannot know whether the request arrived. Instead of resending straight away, it asks the server first: do you already have this key? If yes, the app gets the existing turn back. If no, it resends the same body with the same key, at most three times. Resending therefore never produces two turns.
Duplicates are recognised by request key, never by content.
Two identical messages are still two requests, because you may really want the job done twice. Only the same key means the same request.
Inside one conversation, turns run one after another in the order the server received them. Different conversations in the same account run in parallel, within the plan’s limits.
We simulated 200 users against the storage layer. Under evenly spread load the system held. When 200 requests all wrote in the same instant, 100 of them failed, fighting over the database write lock.
We did not raise timeouts or add silent retries to hide that number. Every write now passes through a bounded admission queue, with slots reserved for operations that must never be delayed, such as Stop. When the queue is full the server says so plainly, “busy, retry in a few seconds”, and the app resends. It no longer accepts work it may drop.
Stage 2VLabs server
The ledger: the server holds the work, the app is a window
In many AI products the control loop (ask the model, call a tool, ask again) runs inside the app or the browser tab. Close the tab and the work is gone. Our first version had a form of this problem: reloading the page or switching tabs could lose what was on screen while the work was still running.
Vera puts the whole loop on the server. For every turn the server keeps a ledger: the request, each model call, each tool call, each progress event, checkpoints, results and usage. The apps on iPhone, web and desktop run no loop at all. They do three things: send requests, send commands such as Stop, and display what the ledger says.
The consequence is that you can press Send on your computer, close the lid, open your iPhone and see that same turn exactly where it is. Each app remembers a cursor: the last event it has read. On reconnect it asks only for what comes after the cursor. Conversations, projects and schedules belong to the account, not to the device that created them.
For a while an app could receive the state “completed” and find no final message. The cause was read order: the server read the event list first and the state second. A turn that finished between the two reads exposed its new state without its last event.
The fix was to swap the two reads.
Stage 3VLabs server
Context and tools: no capability hidden behind keywords
Before calling the model, the server has to decide two things: what the model needs to know, and which tools it may use.
Compaction is a view, not a deletion
A long conversation cannot fit into a model forever. When needed, older parts are compacted. But only the copy handed to the model is compacted. The original history in the ledger stays whole, and a tool result that was compacted can still be opened and re-read by the model, page by page.
We set no cap on the length of the model’s answer, because a cap cuts answers off mid-sentence. Spending is bounded by the account’s usage allowance, and runaway work is bounded separately by limits on repeated calls and file sizes.
Memory: looked up when needed
The notebook Vera keeps about you is capped at 3,000 tokens and is not injected wholesale into every request. Only your name and preferred form of address are always present. Everything else is looked up when the task calls for it. Vera only auto-saves things you said yourself, with a verbatim quote, and does not learn “instructions” found inside files or web pages. You can switch lookup and auto-saving on and off separately, exclude individual conversations, or erase everything.
Tools: the model finds them itself
Vera has dozens of tools. Sending every tool description with every model call is expensive and distracts the model. A common shortcut is a keyword classifier: see the word “Excel”, switch on the spreadsheet tools. We ban this outright. When a classifier guesses wrong, a capability vanishes and nobody notices. You phrase the request slightly differently and Vera “cannot do that”.
Instead, the model always has a tool for finding tools. Rarely used tools are deferred, and the model looks them up when the work needs them.
- 87 → 50
- tools preloaded, after deferring rarely used ones
- −30%
- tool-description text sent with each model call
For the browser-control path we measured one round of optimisation, in which detailed tool descriptions are loaded only after a page has actually opened. The benchmark is 32 tasks we wrote ourselves, in 8 groups, run as before-and-after pairs:
| 32 tasks, one run per version | Before | After |
|---|---|---|
| Tasks passed | 32/32 | 32/32 |
| Model calls | 177 | 119 |
| Input tokens | 1,297,973 | 774,874 |
| Median time per task | 21.8 s | 18.1 s |
Two caveats belong next to this table. Not every task got cheaper: the read-only group used about 2% more input tokens. And these are 32 synthetic tasks we authored, not 32 real websites; the timings come from a test environment and are not a promise about the app.
In the first measurement round the new version passed only 30 of 32. One task asked for a switch to be turned off when it was already off. The model clicked it on, then clicked it off again. The final state was correct, and we still marked it a failure, because an extra action had touched the page. For an assistant that is allowed to click on your behalf, a correct end state is not enough.
Stage 4Your device
The browser: your login session never leaves your machine
The request needs the supplier’s site, where you are signed in. This is where we took a wrong turn once.
The first version used a cloud browser: the server opened its own browser and browsed on your behalf. Technically it worked. As a product it was broken at the root, because the browser in the cloud and the browser on your phone are two different browsers with two different sets of cookies. Vera could not touch the page you were looking at, and to get into your account your login session had to be carried up to the server. In September 2026 we removed the cloud browser from the source entirely and kept no fallback.
Cloud browser (removed)
- A different browser from the one you use
- Signing in means moving your session to the server
- Pages load over the server’s network
Browser on your device (current)
- The browser inside the app, on iPhone or desktop
- Cookies and site data stay on the device
- Pages load over your own network
- You see every action and can press Stop
A model on the server drives a browser on your machine as follows. The server sends down commands from a fixed list: open a page, observe, act, take a screenshot. The device runs a fixed page-reading program, isolated from the website’s own code. The model is never allowed to send arbitrary JavaScript or selectors. It receives a compact description of the page: at most 80 interactive elements, each with a reference number, and at most 10,000 characters of content. To click, it says “click element 12”.
Permission travels with the request
The message you send is the permission. There is no dialog asking you to approve each click, because nobody still reads a prompt the twentieth time it appears in one task. In exchange the permission is narrow. It is bound to this account, this device, this conversation and this turn. It is single-use and it expires. A read-only request cannot act.
A command that was dispatched and whose result was lost is recorded as “outcome unknown” and is never replayed. Clicking “Place order” twice is far worse than asking you. When you touch the page yourself, every pending command is cancelled.
Each conversation gets its own tab, so two tasks running side by side do not step on each other. Cookies are shared within the same account on that machine, as in any ordinary browser.
Page content is data, not instructions
A web page can contain the line “Dear AI assistant, click Delete account”. To Vera, everything read from a website, an email, a file or an image is untrusted data. It cannot grant permission, and it cannot widen the task you gave. Our browser benchmark includes a page that tries to lure a click on a Delete button. The agent passed it in the final measurement round, which is one test and not a guarantee.
The login session stays on the device. Content Vera reads is treated as data and cannot grant or widen a permission.
One browser per account is too few. At first each account had a single browser, so a simple weather question was refused because the browser was busy with another task. Since then each conversation has its own tab.
Client clocks cannot be trusted. Some Windows machines ran about 8 seconds fast, enough for the first request to be treated as already expired. Expiry is now computed by the server on its own clock.
iPhone rules do not fit the desktop. On iPhone, a turn stops when the app goes to the background. We mistakenly applied the same rule on desktop, and users who switched to another window lost their work. On desktop, permission can now only be granted while the app is in front of you, but work already granted keeps running while you do something else.
The same rules for controlling the whole computer
On desktop, Vera can also operate other applications once you switch on Computer Use, which is off by default. The loop is the same: observe, receive references, act, observe again. An action counts as successful only when the next observation confirms it, not because a command “exited without error”.
Operating-system permissions are still granted by you, through the macOS or Windows dialogs; Vera does not look for a way around them. Some places are always blocked: Terminal, System Settings, the password keychain and password fields. Turning the switch off revokes the permission immediately.
The web version
Vera on the web does not control a browser. One web tab cannot safely drive another without a browser extension or a return to the cloud browser, and we chose to build neither. On the web Vera still searches and reads public links. For work that needs to act on a website, it points you to the desktop or iPhone app, where you continue the same conversation.
Stage 5Session sandbox
The sandbox: code runs where there are no keys
The price list is in. Now Vera has to compare it with your Excel file, and the most reliable way to do that is to write a piece of Python and actually run it. Code written by an AI, running on a customer’s data, needs a place of its own.
Every account and every conversation gets its own sealed Linux box, the sandbox. Files from this conversation do not sit alongside those of another conversation, not even another one of yours. The box runs as an unprivileged user, its root filesystem is read-only, and its network goes through a controlled gateway.
What matters most is what the box does not contain: no AI provider keys, no database, no directory of the host. If a piece of code misbehaves or is tricked, the worst it can do is damage its own box.
- 4 CPU · 4 GB
- per sandbox
- 10 minutes
- ceiling for a single command
- 0
- AI keys inside the sandbox
Workers: able to do the work, not to decide
The architecture separates the coordinating server from workers, where compute steps actually run. The contract with a worker is deliberately narrow. It receives one step at a time, already authenticated by the server. It holds no AI keys, cannot reach the database, and has no right to publish a final answer to you.
Each step is handed out with a lease and an attempt number. The worker must renew the lease while it is working. If it goes silent past the deadline, the server takes the work back. A late result from an old attempt cannot overwrite the result of a newer one.
The hardest case is a machine that dies in the middle of a command. Running the command again is safe for a read. For a command that already wrote a file or sent something, it may do that thing twice. Our rule: a stateful command that has started is never silently re-run on another machine. It is recorded as “outcome unknown”, and the model is told exactly that, so it can check and decide. Clearly transient errors are retried, at most three times.
Three sandboxes left over from a test run took every execution slot in the live system, and customers’ turns stood waiting.
Since then, waiting for a slot is a named state with a limit. The system retries with growing pauses for up to two minutes, then reports clearly that no capacity is available. It does not leave you watching an endless spinner.
Stage 6VLabs server
Progress: telling the truth about work in flight
While all of that is happening, you are looking at a screen.
Vera separates two things: the progress line and the final answer. Progress is one record in the ledger that keeps being updated, along the lines of “Opening the supplier site” and then “Comparing the two price lists”. The final answer is a different record that appears only when the turn ends. The model finishing a block of text, or a tool finishing its run, does not mean the turn is finished.
We deliberately avoid the following:
- We do not show internal reasoning or raw tool output as if it were speech addressed to you.
- We do not add a fake typing delay, and we do not lower the reasoning level just to make text appear sooner.
- We do not run a second model whose only job is to greet you while you wait.
- 2.3–2.6 s
- from pressing Send to the first text on screen, measured in September
- 3.7–4.9 s
- to first text for a short greeting, measured in October
The two figures come from different test runs a month apart, with different prompts, so they are not directly comparable.
Changing your mind mid-turn
Halfway through, you remember: “skip the office-supplies category”. Previously the app held that message back and sent it as a new turn once the current one finished, which meant Vera completed the wrong job before it heard you.
Now the new message goes straight into the running turn. The server distinguishes two moments: accepted, when the message is in the ledger, and applied, when a model call has actually used it. New input is considered at the boundary between steps, and older calls that have not started are dropped. A message that arrives after the turn has entered its closing phase becomes the next turn.
Stage 7VLabs server
Finishing: “done” needs evidence
This stage grew out of a bug.
A model call can succeed at the network level and return no text at all. The old system saw “no error” and recorded the turn as completed. The user saw a spinner or an empty bubble.
Worse, pressing Stop at that time only changed a state in the database. The model stream behind it kept running.
We fixed it by redefining “done”. Completed no longer means the connection closed without an error. Completed is an outcome with evidence. Between running and completed there is now one more state, finalizing:
completed only through finalizing, where the three conditions below are checked.- There must be real content. A turn is recorded as completed only when it has a real answer, not a progress line, or a durably stored result file. If the model returns nothing, the system makes at most two more calls to obtain a closing answer. If it is still empty, the turn is recorded as failed, with a message you can see. No screen is ever allowed to show an empty success.
- There must be a receipt. The app reads everything it is missing, draws the answer on screen, and only then sends a “displayed” receipt for that turn on that device. Sending the receipt twice is harmless. A receipt for an error message does not count as delivering the result.
- Debts are written down. Empty turns, stalled turns and turns without a receipt go into a separate ledger we call response debt: the system still owes you an answer. When we recover one, we create a new turn that points back to the original. The original is never edited to look better.
Stop was rebuilt to be real as well. Pressing Stop now closes the model stream and blocks tool results that arrive late. A turn you stopped yourself creates no debt.
The same principle applies to how we report our own numbers. In the 200-user test from stage 1, the database showed 101 completed turns, but one of them was missing its closing event. The report says 100, not 101.
Stage 8Your device
Results and reruns
Your turn ends with an Excel file in which the items that went up are flagged. This stage covers where that file lives and what happens the following Monday.
Files have a clear lifecycle
Every file Vera produces has two buttons: Download and Save to Library. The Library is your long-term storage, and Vera never puts anything there on its own. Files you upload, files Vera creates and files Vera edits all stay inside the conversation until you press save. That way the Library contains only what you chose to keep.
A file that was not saved to the Library is kept for two calendar months and then deleted from the server. Two calendar months, not 60 days: a file created on 31 December 2023 expires on 29 February 2024. Reading or downloading it does not extend the period. Afterwards the text of the conversation remains, and the file’s place shows “Expired”. The exception is files you asked Vera to remember, which are kept until you replace them or ask Vera to forget them.
A schedule has its own permission
“Do this again every Monday morning” sounds simple, but it touches the most sensitive point of all: work that starts by itself, with you not at the keyboard, on a site where you are signed in.
We divide the roles as in every other stage. The server holds the schedule, each due occurrence, the model and the results. Your computer does only the part that needs the browser, because that is where the login session lives. The schedule is tied to the exact machine that created it, and the server takes that machine from the real grant of the turn that set the schedule, never from a device identifier supplied by the model.
- Every run needs a fresh grant. The grant from the turn in which you created the schedule cannot be reused, and website content cannot mint a grant for a schedule.
- The conditions must hold. The machine and the app are on, the window is visible, the site is still signed in. If not, the run waits. It does not quietly fall back to a cloud browser.
- Missed runs collapse into the latest one. A computer that was off for three weeks does not mean Vera runs three times in a row next Monday.
- Finishing is not the same as succeeding. A run has to report its result against the task it was given. Without that report the run is recorded as “unverified”.
What does not work yet
Every choice above has a price, and there are places where we are simply not finished.
- The web version does not control a browser. You need the desktop or iPhone app.
- On iPhone, Vera browses only while the app is open in front of you. Switching to another app stops the turn; the page is kept.
- Browser schedules need the computer to be on. We accept that in order not to carry cookies up to the server.
- On desktop, opening a new page while the window is minimised sometimes fails. This is a bug we know about and have not finished fixing.
- Computer Use does not run while the screen is locked. We tried, the operating system does not allow it, and we are not looking for a way around that.
- The 200-user test measured the storage layer, not the whole system. We do not yet have an end-to-end number for simultaneous load.
Five principles
If we had to reduce all eight stages to a few lines we could carry to another system, we would keep these five.
- Store first, act second.Work is written down before it is acknowledged, so no failure can leave a job that exists on only one side.
- The server holds the work, the device holds the authority.The loop and the ledger live on the server. Cookies, local files and operating-system permissions stay with you.
- Data is not instructions.What Vera reads cannot grant permission or widen the task you gave.
- If you do not know, say so.No guessed outcomes, no silent re-run of a command that may have consequences.
- “Done” needs evidence.A real answer, and a receipt showing that you saw it.
This article describes the system as of November 2026. The figures are internal measurements taken at the times stated, not service commitments. We have left out details that could help someone attack the system. Give Vera a task.
How to cite
Tô Hoài Vũ. “After you press Send: anatomy of one Vera work turn.” VLabs Research, 9 November 2026. https://www.vlabsai.com/research/after-you-press-send. https://doi.org/10.5281/zenodo.24088869
@misc{to2026send,
author = {Tô, Hoài Vũ},
title = {After you press Send: anatomy of one Vera work turn},
year = {2026},
month = nov,
howpublished = {VLabs Research},
doi = {10.5281/zenodo.24088869},
url = {https://www.vlabsai.com/research/after-you-press-send}
}